k8s学习笔记-14-服务发现Service

[TOC] 一、Service的概念 运行在Pod中的应用是向客户端提供服务的守护进程,比如,nginx、tomcat、etcd等等,它们都是受控于控制器的资源对象,存在生命周期,我们知道Pod资源对象在自愿或非自愿终端后,只能被重构的Pod对象所替代,属于不可再生类组件。而在动态和弹性的管理模式下,Service为该类Pod对象提供了一个固定、统一的访问接口和负载均衡能力。 其实,就是说Pod存在生命周期,有销毁,有重建,无法提供一个固定的访问接口给客户端。并且为了同类的Pod都能够实现工作负载的价值,由此Service资源出现了,可以为一类Pod资源对象提供一个固定的访问接口和负载均衡,类似于阿里云的负载均衡或者是LVS的功能。 但是要知道的是,Service和Pod对象的IP地址,一个是虚拟地址,一个是Pod IP地址,都仅仅在集群内部可以进行访问,无法接入集群外部流量。而为了解决该类问题的办法可以是在单一的节点上做端口暴露(hostPort)以及让Pod资源共享工作节点的网络名称空间(hostNetwork)以外,还可以使用NodePort或者是LoadBalancer类型的Service资源,或者是有7层负载均衡能力的Ingress资源。 Service是Kubernetes的核心资源类型之一,Service资源基于标签选择器将一组Pod定义成一个逻辑组合,并通过自己的IP地址和端口调度代理请求到组内的Pod对象,如下图所示,它向客户端隐藏了真实的,处理用户请求的Pod资源,使得从客户端上看,就像是由Service直接处理并响应一样,是不是很像负载均衡器呢! Service对象的IP地址也称为Cluster IP,它位于为Kubernetes集群配置指定专用的IP地址范围之内,是一种虚拟的IP地址,它在Service对象创建之后保持不变,并且能够被同一集群中的Pod资源所访问。Service端口用于接受客户端请求,并将请求转发至后端的Pod应用的相应端口,这样的代理机制,也称为端口代理,它是基于TCP/IP 协议栈的传输层。 二、Service的实现模型 在 Kubernetes 集群中,每个 Node 运行一个 kube-proxy 进程。kube-proxy 负责为 Service 实现了一种 VIP(虚拟 IP)的形式,而不是 ExternalName 的形式。 在 Kubernetes v1.0 版本,代理完全在 userspace。在 Kubernetes v1.1 版本,新增了 iptables 代理,但并不是默认的运行模式。 从 Kubernetes v1.2 起,默认就是 iptables 代理。在Kubernetes v1.8.0-beta.0中,添加了ipvs代理。在 Kubernetes v1.0 版本,Service 是 “4层”(TCP/UDP over IP)概念。 在 Kubernetes v1.1 版本,新增了 Ingress API(beta 版),用来表示 “7层”(HTTP)服务。 kube-proxy 这个组件始终监视着apiserver中有关service的变动信息,获取任何一个与service资源相关的变动状态,通过watch监视,一旦有service资源相关的变动和创建,kube-proxy都要转换为当前节点上的能够实现资源调度规则(例如:iptables、ipvs) 2.1、userspace代理模式 这种模式,当客户端Pod请求内核空间的service iptables后,把请求转到给用户空间监听的kube-proxy 的端口,由kube-proxy来处理后,再由kube-proxy将请求转给内核空间的 service ip,再由service iptalbes根据请求转给各节点中的的service pod。 ...

August 29, 2018

k8s学习笔记-12-Pod控制器--ReplicaSet、Deployment

[TOC] 一、Pod控制器及其功用 Pod控制器是用于实现管理pod的中间层,确保pod资源符合预期的状态,pod的资源出现故障时,会尝试 进行重启,当根据重启策略无效,则会重新新建pod的资源。 pod控制器有多种类型: ReplicaSet: 代用户创建指定数量的pod副本数量,确保pod副本数量符合预期状态,并且支持滚动式自动扩容和缩容功能。 ReplicaSet主要三个组件组成: (1)用户期望的pod副本数量 (2)标签选择器,判断哪个pod归自己管理 (3)当现存的pod数量不足,会根据pod资源模板进行新建 帮助用户管理无状态的pod资源,精确反应用户定义的目标数量,但是RelicaSet不是直接使用的控制器,而是使用Deployment。 **Deployment:**工作在ReplicaSet之上,用于管理无状态应用,目前来说最好的控制器。支持滚动更新和回滚功能,还提供声明式配置。 **DaemonSet:**用于确保集群中的每一个节点只运行特定的pod副本,通常用于实现系统级后台任务。比如ELK服务 特性:服务是无状态的 服务必须是守护进程 **Job:**只要完成就立即退出,不需要重启或重建。 **Cronjob:**周期性任务控制,不需要持续后台运行, **StatefulSet:**管理有状态应用 二、ReplicaSet控制器 ReplicationController用来确保容器应用的副本数始终保持在用户定义的副本数,即如果有容器异常退出,会自动创建新的Pod来替代;而如果异常多出来的容器也会自动回收。 在新版本的Kubernetes中建议使用ReplicaSet来取代ReplicationController。ReplicaSet跟ReplicationController没有本质的不同,只是名字不一样,并且ReplicaSet支持集合式的selector。 虽然ReplicaSet可以独立使用,但一般还是建议使用 Deployment 来自动管理ReplicaSet,这样就无需担心跟其他机制的不兼容问题(比如ReplicaSet不支持rolling-update但Deployment支持)。 ReplicaSet示例: (1)命令行查看ReplicaSet清单定义规则 [root@k8s-master ~]# kubectl explain rs [root@k8s-master ~]# kubectl explain rs.spec [root@k8s-master ~]# kubectl explain rs.spec.template (2)新建ReplicaSet示例 [root@k8s-master ~]# vim rs-demo.yaml apiVersion: apps/v1 #api版本定义 kind: ReplicaSet #定义资源类型为ReplicaSet metadata: #元数据定义 name: myapp namespace: default spec: #ReplicaSet的规格定义 replicas: 2 #定义副本数量为2个 selector: #标签选择器,定义匹配pod的标签 matchLabels: app: myapp release: canary template: #pod的模板定义 metadata: #pod的元数据定义 name: myapp-pod #自定义pod的名称 labels: #定义pod的标签,需要和上面定义的标签一致,也可以多出其他标签 app: myapp release: canary environment: qa spec: #pod的规格定义 containers: #容器定义 - name: myapp-container #容器名称 image: ikubernetes/myapp:v1 #容器镜像 ports: #暴露端口 - name: http containerPort: 80 (3)创建ReplicaSet定义的pod [root@k8s-master ~]# kubectl create -f rs-demo.yaml [root@k8s-master ~]# kubectl get pods #获取pod信息 [root@k8s-master ~]# kubectl describe pods myapp-*** #查看pod详细信息 (4)修改pod的副本数量 [root@k8s-master ~]# kubectl edit rs myapp replicas: 5 [root@k8s-master ~]# kubectl get rs -o wide (5)修改pod的镜像版本 [root@k8s-master ~]# kubectl edit rs myapp image: ikubernetes/myapp:v2 [root@k8s-master ~]# kubectl delete pods myapp-*** #修改了pod镜像版本,pod需要重建才能达到最新版本 [root@k8s-master ~]# kubectl create -f rs-demo.yaml 三、Deployment控制器 Deployment为Pod和ReplicaSet(下一代Replication Controller)提供声明式更新。 ...

August 28, 2018

k8s学习笔记-11-Pod状态和生命周期管理

[TOC] 一、什么是Pod? Pod是kubernetes中你可以创建和部署的最小也是最简的单位。一个Pod代表着集群中运行的一个进程。 Pod中封装着应用的容器(有的情况下是好几个容器),存储、独立的网络IP,管理容器如何运行的策略选项。Pod代表着部署的一个单位:kubernetes中应用的一个实例,可能由一个或者多个容器组合在一起共享资源。 在Kubrenetes集群中Pod有如下两种使用方式: 一个Pod中运行一个容器。“每个Pod中一个容器”的模式是最常见的用法;在这种使用方式中,你可以把Pod想象成是单个容器的封装,kuberentes管理的是Pod而不是直接管理容器。 在一个Pod中同时运行多个容器。一个Pod中也可以同时封装几个需要紧密耦合互相协作的容器,它们之间共享资源。这些在同一个Pod中的容器可以互相协作成为一个service单位——一个容器共享文件,另一个“sidecar”容器来更新这些文件。Pod将这些容器的存储资源作为一个实体来管理。 Pod中共享的环境包括Linux的namespace,cgroup和其他可能的隔绝环境,这一点跟Docker容器一致。在Pod的环境中,每个容器中可能还有更小的子隔离环境。 Pod中的容器共享IP地址和端口号,它们之间可以通过localhost互相发现。它们之间可以通过进程间通信,需要明白的是同一个Pod下的容器是通过lo网卡进行通信。例如SystemV信号或者POSIX共享内存。不同Pod之间的容器具有不同的IP地址,不能直接通过IPC通信。 Pod中的容器也有访问共享volume的权限,这些volume会被定义成pod的一部分并挂载到应用容器的文件系统中。 就像每个应用容器,pod被认为是临时实体。在Pod的生命周期中,pod被创建后,被分配一个唯一的ID(UID),调度到节点上,并一致维持期望的状态直到被终结(根据重启策略)或者被删除。如果node死掉了,分配到了这个node上的pod,在经过一个超时时间后会被重新调度到其他node节点上。一个给定的pod(如UID定义的)不会被“重新调度”到新的节点上,而是被一个同样的pod取代,如果期望的话甚至可以是相同的名字,但是会有一个新的UID(查看replication controller获取详情)。 二、Pod中如何管理多个容器? Pod中可以同时运行多个进程(作为容器运行)协同工作。同一个Pod中的容器会自动的分配到同一个 node 上。同一个Pod中的容器共享资源、网络环境和依赖,它们总是被同时调度。 注意在一个Pod中同时运行多个容器是一种比较高级的用法。只有当你的容器需要紧密配合协作的时候才考虑用这种模式。例如,你有一个容器作为web服务器运行,需要用到共享的volume,有另一个“sidecar”容器来从远端获取资源更新这些文件,如下图所示: Pod中可以共享两种资源:网络和存储。 网络 每个Pod都会被分配一个唯一的IP地址。Pod中的所有容器共享网络空间,包括IP地址和端口。Pod内部的容器可以使用localhost互相通信。Pod中的容器与外界通信时,必须分配共享网络资源(例如使用宿主机的端口映射)。 存储: 可以Pod指定多个共享的Volume。Pod中的所有容器都可以访问共享的volume。Volume也可以用来持久化Pod中的存储资源,以防容器重启后文件丢失。 三、使用Pod 通常把Pod分为两类: **自主式Pod :**这种Pod本身是不能自我修复的,当Pod被创建后(不论是由你直接创建还是被其他Controller),都会被Kuberentes调度到集群的Node上。直到Pod的进程终止、被删掉、因为缺少资源而被驱逐、或者Node故障之前这个Pod都会一直保持在那个Node上。Pod不会自愈。如果Pod运行的Node故障,或者是调度器本身故障,这个Pod就会被删除。同样的,如果Pod所在Node缺少资源或者Pod处于维护状态,Pod也会被驱逐。 **控制器管理的Pod:**Kubernetes使用更高级的称为Controller的抽象层,来管理Pod实例。Controller可以创建和管理多个Pod,提供副本管理、滚动升级和集群级别的自愈能力。例如,如果一个Node故障,Controller就能自动将该节点上的Pod调度到其他健康的Node上。虽然可以直接使用Pod,但是在Kubernetes中通常是使用Controller来管理Pod的。如下图: 每个Pod都有一个特殊的被称为“根容器”的Pause 容器。 Pause容器对应的镜像属于Kubernetes平台的一部分,除了Pause容器,每个Pod还包含一个或者多个紧密相关的用户业务容器。 Kubernetes设计这样的Pod概念和特殊组成结构有什么用意????? 原因一:在一组容器作为一个单元的情况下,难以对整体的容器简单地进行判断及有效地进行行动。比如,一个容器死亡了,此时是算整体挂了么?那么引入与业务无关的Pause容器作为Pod的根容器,以它的状态代表着整个容器组的状态,这样就可以解决该问题。 原因二:Pod里的多个业务容器共享Pause容器的IP,共享Pause容器挂载的Volume,这样简化了业务容器之间的通信问题,也解决了容器之间的文件共享问题。 四、Pod的持久性和终止 (1)Pod的持久性 Pod在设计支持就不是作为持久化实体的。在调度失败、节点故障、缺少资源或者节点维护的状态下都会死掉会被驱逐。 通常,用户不需要手动直接创建Pod,而是应该使用controller(例如Deployments),即使是在创建单个Pod的情况下。Controller可以提供集群级别的自愈功能、复制和升级管理。 (2)Pod的终止 因为Pod作为在集群的节点上运行的进程,所以在不再需要的时候能够优雅的终止掉是十分必要的(比起使用发送KILL信号这种暴力的方式)。用户需要能够放松删除请求,并且知道它们何时会被终止,是否被正确的删除。用户想终止程序时发送删除pod的请求,在pod可以被强制删除前会有一个宽限期,会发送一个TERM请求到每个容器的主进程。一旦超时,将向主进程发送KILL信号并从API server中删除。如果kubelet或者container manager在等待进程终止的过程中重启,在重启后仍然会重试完整的宽限期。 示例流程如下: 用户发送删除pod的命令,默认宽限期是30秒; 在Pod超过该宽限期后API server就会更新Pod的状态为“dead”; 在客户端命令行上显示的Pod状态为“terminating”; 跟第三步同时,当kubelet发现pod被标记为“terminating”状态时,开始停止pod进程: 如果在pod中定义了preStop hook,在停止pod前会被调用。如果在宽限期过后,preStop hook依然在运行,第二步会再增加2秒的宽限期; 向Pod中的进程发送TERM信号; 跟第三步同时,该Pod将从该service的端点列表中删除,不再是replication controller的一部分。关闭的慢的pod将继续处理load balancer转发的流量; 过了宽限期后,将向Pod中依然运行的进程发送SIGKILL信号而杀掉进程。 Kublete会在API server中完成Pod的的删除,通过将优雅周期设置为0(立即删除)。Pod在API中消失,并且在客户端也不可见。 删除宽限期默认是30秒。kubectl delete 命令支持 —grace-period=<seconds> 选项,允许用户设置自己的宽限期。如果设置为0将强制删除pod。在kubectl>=1.5版本的命令中,你必须同时使用 --force 和 --grace-period=0 来强制删除pod。 ...

August 27, 2018

k8s学习笔记-10-资源清单定义

[TOC] 一、Kubernetes常用资源 以下列举的内容都是 kubernetes 中的 Object,这些对象都可以在 yaml 文件中作为一种 API 类型来配置。 类别 名称 工作负载型资源对象 Pod Replicaset ReplicationController Deployments StatefulSets Daemonset Job CronJob 服务发现及负载均衡 Service Ingress 配置与存储 Volume、Persistent Volume、CSl 、 configmap、 secret 集群资源 Namespace Node Role ClusterRole RoleBinding ClusterRoleBinding 元数据资源 HPA PodTemplate LimitRang 二、理解Kubernetes中的对象 在 Kubernetes 系统中,Kubernetes 对象 是持久化的条目。Kubernetes 使用这些条目去表示整个集群的状态。特别地,它们描述了如下信息: 什么容器化应用在运行(以及在哪个 Node 上) 可以被应用使用的资源 关于应用如何表现的策略,比如重启策略、升级策略,以及容错策略 Kubernetes 对象是 “目标性记录” —— 一旦创建对象,Kubernetes 系统将持续工作以确保对象存在。通过创建对象,可以有效地告知 Kubernetes 系统,所需要的集群工作负载看起来是什么样子的,这就是 Kubernetes 集群的 期望状态。 与 Kubernetes 对象工作 —— 是否创建、修改,或者删除 —— 需要使用 Kubernetes API。当使用 kubectl 命令行接口时,比如,CLI 会使用必要的 Kubernetes API 调用,也可以在程序中直接使用 Kubernetes API。 ...

August 25, 2018

k8s学习笔记-09-kubernetes命令式快速创建应用

[TOC] 1、使用命令kubectl run创建应用 语法: kubectl run NAME --image=image [--env="key=value"] [--port=port] [--replicas=replicas] [--dry-run=bool] [--overrides=inline-json] [--command] -- [COMMAND] [args...] [options] 实用举例 [root@k8s-master ~]# kubectl run nginx-deploy --image=nginx:1.14-alpine --port=80 --replicas=1 #创建一个nginx的应用,副本数为1 deployment.apps/nginx-deploy created [root@k8s-master ~]# kubectl get deployment #获取应用信息,查看应用是否符合预期状态 NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE nginx-deploy 1 1 1 1 40s [root@k8s-master ~]# kubectl get pods #获取pod信息 NAME READY STATUS RESTARTS AGE nginx-deploy-5b595999-44zwq 1/1 Running 0 1m [root@k8s-master ~]# kubectl get pods -o wide #查看pod运行在哪个节点上 NAME READY STATUS RESTARTS AGE IP NODE nginx-deploy-5b595999-44zwq 1/1 Running 0 1m 10.244.2.2 k8s-node02 从上面创建的应用可以得知,nginx-deploy应用的pod的ip为10.244.2.2,这是一个pod ip,仅仅可以在集群内部访问,如下: ...

August 19, 2018

k8s学习笔记-08-Kubeadm部署集群

[TOC] 一、环境说明 节点名称 ip地址 部署说明 Pod 网段 Service网段 系统说明 k8s-master 192.168.56.11 docker、kubeadm、kubectl、kubelet 10.244.0.0/16 10.96.0.0/12 Centos 7.4 k8s-node01 192.168.56.12 docker、kubeadm、kubelet 10.244.0.0/16 10.96.0.0/12 Centos 7.4 k8s-node02 192.168.56.13 docker、kubeadm、kubelet 10.244.0.0/16 10.96.0.0/12 Centos 7.4 (1)配置源 [root@k8s-master ~]# cd /etc/yum.repos.d/ 配置阿里云的源:https://opsx.alibaba.com/mirror [root@k8s-master yum.repos.d]# wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo #配置dokcer源 [root@k8s-master ~]# cat <<EOF > /etc/yum.repos.d/kubernetes.repo #配置kubernetes源 > [kubernetes] > name=Kubernetes > baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/ > enabled=1 > gpgcheck=1 > repo_gpgcheck=1 > gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg > EOF [root@k8s-master yum.repos.d]# yum repolist #查看可用源 将源拷贝到node01和node02节点 ...

August 18, 2018

k8s学习笔记-07-Coredns和Dashboard部署

[TOC] 一、CoreDNS部署 在 Cluster 中,除了可以通过 Cluster IP 访问 Service,Kubernetes 还提供了更为方便的 DNS 访问。 (1)编辑coredns.yaml文件 [root@linux-node1 ~]# vim coredns.yaml apiVersion: v1 kind: ServiceAccount metadata: name: coredns namespace: kube-system labels: kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: kubernetes.io/bootstrapping: rbac-defaults addonmanager.kubernetes.io/mode: Reconcile name: system:coredns rules: - apiGroups: - "" resources: - endpoints - services - pods - namespaces verbs: - list - watch --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: annotations: rbac.authorization.kubernetes.io/autoupdate: "true" labels: kubernetes.io/bootstrapping: rbac-defaults addonmanager.kubernetes.io/mode: EnsureExists name: system:coredns roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: system:coredns subjects: - kind: ServiceAccount name: coredns namespace: kube-system --- apiVersion: v1 kind: ConfigMap metadata: name: coredns namespace: kube-system labels: addonmanager.kubernetes.io/mode: EnsureExists data: Corefile: | .:53 { errors health kubernetes cluster.local. in-addr.arpa ip6.arpa { pods insecure upstream fallthrough in-addr.arpa ip6.arpa } prometheus :9153 proxy . /etc/resolv.conf cache 30 } --- apiVersion: extensions/v1beta1 kind: Deployment metadata: name: coredns namespace: kube-system labels: k8s-app: coredns kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile kubernetes.io/name: "CoreDNS" spec: replicas: 2 strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 1 selector: matchLabels: k8s-app: coredns template: metadata: labels: k8s-app: coredns spec: serviceAccountName: coredns tolerations: - key: node-role.kubernetes.io/master effect: NoSchedule - key: "CriticalAddonsOnly" operator: "Exists" containers: - name: coredns image: coredns/coredns:1.0.6 imagePullPolicy: IfNotPresent resources: limits: memory: 170Mi requests: cpu: 100m memory: 70Mi args: [ "-conf", "/etc/coredns/Corefile" ] volumeMounts: - name: config-volume mountPath: /etc/coredns ports: - containerPort: 53 name: dns protocol: UDP - containerPort: 53 name: dns-tcp protocol: TCP livenessProbe: httpGet: path: /health port: 8080 scheme: HTTP initialDelaySeconds: 60 timeoutSeconds: 5 successThreshold: 1 failureThreshold: 5 dnsPolicy: Default volumes: - name: config-volume configMap: name: coredns items: - key: Corefile path: Corefile --- apiVersion: v1 kind: Service metadata: name: coredns namespace: kube-system labels: k8s-app: coredns kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile kubernetes.io/name: "CoreDNS" spec: selector: k8s-app: coredns clusterIP: 10.1.0.2 ports: - name: dns port: 53 protocol: UDP - name: dns-tcp port: 53 protocol: TCP (2)创建coredns [root@linux-node1 ~]# kubectl create -f coredns.yaml serviceaccount "coredns" created clusterrole.rbac.authorization.k8s.io "system:coredns" created clusterrolebinding.rbac.authorization.k8s.io "system:coredns" created configmap "coredns" created deployment.extensions "coredns" created service "coredns" created (3)查看coredns服务 [root@linux-node1 ~]# kubectl get deployment -n kube-system NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE coredns 2 2 2 0 1m [root@linux-node1 ~]# kubectl get svc -n kube-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE coredns ClusterIP 10.1.0.2 <none> 53/UDP,53/TCP 1m [root@linux-node1 ~]# kubectl get pod -n kube-system NAME READY STATUS RESTARTS AGE coredns-77c989547b-d84n8 1/1 Running 0 2m coredns-77c989547b-j4ms2 1/1 Running 0 2m (4)Pod容器中进行域名解析测试 [root@linux-node1 ~]# kubectl run alpine --rm -ti --image=alpine -- /bin/sh If you don't see a command prompt, try pressing enter. / # nslookup httpd-svc nslookup: can't resolve '(null)': Name does not resolve Name: httpd-svc Address 1: 10.1.230.129 / # wget httpd-svc:8080 Connecting to httpd-svc:8080 (10.1.230.129:8080) index.html 100% |********************************************************************************************************************************************| 45 0:00:00 ETA 二、Dashboard部署 从github上下载dashboard的yaml文件:https://github.com/unixhot/salt-kubernetes ...

August 17, 2018

k8s学习笔记-06-创建K8S应用

[TOC] 一、Deployment的概念 K8S本身并不提供网络的功能,所以需要借助第三方网络插件进行部署K8S中的网络,以打通各个节点中容器的互通。 POD,是K8S中的一个逻辑概念,K8S管理的是POD,一个POD中包含多个容器,容器之间通过localhost互通。而POD需要ip地址。每个POD都有一个标签 POD–>RC–>RS–>Deployment (发展历程) Deployment,表示用户对K8S集群的一次更新操作。Deployment是一个比RS应用模式更广的API对象。用于保证Pod的副本的数量。 可以是创建一个新的服务,更新一个新的服务,也可以是滚动升级一个服务。滚动升级一个服务。实际是创建一个新的RS,然后将新的RS中副本数增加到理想状态,将旧的RS中的副本数减小到0的复合操作; 这样的一个复合操作用一个RS是不太好描述的,所以用一个更通用的Deployment来描述。 RC、RS和Deployment只是保证了支撑服务的POD数量,但是没有解决如何访问这些服务的问题。一个POD只是一个运行服务的实例,随时可以能在一个节点上停止,在另一个节点以一个新的IP启动一个新的POD,因此不能以确定的IP和端口号提供服务。 要稳定地提供服务需要服务发现和负载均衡能力。服务发现完成的工作,是针对客户端访问的服务,找到对应的后端服务实例。 在K8S的集中当中,客户端需要访问的服务就是Service对象。每个Service会对应一个集群内部有效的虚拟IP,集群内部通过虚拟IP访问一个服务。 二、创建K8S的第一个应用 [root@linux-node1 ~]# kubectl run net-test --image=alpine --replicas=2 sleep 36000 #创建名称为net-test的应用,镜像指定为alpine,副本数为2个 deployment.apps "net-test" created [root@linux-node1 ~]# kubectl get pod -o wide #查看pod的状态信息,此时是API Server从etcd中读取这些数据 NAME READY STATUS RESTARTS AGE IP NODE net-test-7b949fc785-2v2qz 1/1 Running 0 56s 10.2.87.2 192.168.56.120 net-test-7b949fc785-6nrhm 0/1 ContainerCreating 0 56s <none> 192.168.56.130 [root@linux-node1 ~]# kubectl get deployment net-test NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE net-test 2 2 2 2 22h kubectl get deployment命令可以查看net-test的状态,输出显示两个副本正常运行。还可以在创建的过程中,通过kubectl describe deployment net-test了解详细的信息。 [root@linux-node1 ~]# kubectl describe deployment net-test Name: net-test Namespace: default CreationTimestamp: Thu, 16 Aug 2018 15:41:29 +0800 Labels: run=net-test Annotations: deployment.kubernetes.io/revision=1 Selector: run=net-test Replicas: 2 desired | 2 updated | 2 total | 2 available | 0 unavailable StrategyType: RollingUpdate MinReadySeconds: 0 RollingUpdateStrategy: 1 max unavailable, 1 max surge Pod Template: Labels: run=net-test Containers: net-test: Image: alpine Port: <none> Host Port: <none> Args: sleep 360000 Environment: <none> Mounts: <none> Volumes: <none> Conditions: Type Status Reason ---- ------ ------ Available True MinimumReplicasAvailable Progressing True NewReplicaSetAvailable OldReplicaSets: <none> NewReplicaSet: net-test-5767cb94df (2/2 replicas created) Events: <none> Events是Deployment的日志,记录整个RelicaSet的启动过程,从上面的创建过程,可以看到Deployment是通过ReplicaSet来管理Pod。 ...

August 16, 2018

k8s学习笔记-05-Flannel部署

[TOC] 一、K8S的ip地址 **Node IP:**节点设备的IP,如物理机,虚拟机等容器宿主的实际IP。 **Pod IP:**Pod的IP地址,是根据docker0网络IP段进行分配的。 **Cluster IP:**Service的IP,是一个虚拟IP,仅作用于service对象,由K8S管理和分配,需要结合service port才能使用,单独的IP没有通信功能,集群外访问需要一些修改。 在K8S集群内部,node ip、pod ip、clustere ip的通信机制是由k8s指定的路由规则,不是IP路由。 [root@linux-node1 ~]# kubectl get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.1.0.1 <none> 443/TCP 3h 二、Flannel网络部署 (1)为Flannel生成证书 [root@linux-node1 ssl]# vim flanneld-csr.json { "CN": "flanneld", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "BeiJing", "L": "BeiJing", "O": "k8s", "OU": "System" } ] } (2)生成证书 [root@linux-node1 ssl]# cfssl gencert -ca=/opt/kubernetes/ssl/ca.pem \ > -ca-key=/opt/kubernetes/ssl/ca-key.pem \ > -config=/opt/kubernetes/ssl/ca-config.json \ > -profile=kubernetes flanneld-csr.json | cfssljson -bare flanneld [root@linux-node1 ssl]# ll flannel* -rw-r--r-- 1 root root 997 May 31 11:13 flanneld.csr -rw-r--r-- 1 root root 221 May 31 11:13 flanneld-csr.json -rw------- 1 root root 1675 May 31 11:13 flanneld-key.pem -rw-r--r-- 1 root root 1391 May 31 11:13 flanneld.pem (3)分发证书 [root@linux-node1 ssl]# cp flanneld*.pem /opt/kubernetes/ssl/ [root@linux-node1 ssl]# scp flanneld*.pem 192.168.56.120:/opt/kubernetes/ssl/ flanneld-key.pem 100% 1675 127.2KB/s 00:00 flanneld.pem 100% 1391 308.3KB/s 00:00 [root@linux-node1 ssl]# scp flanneld*.pem 192.168.56.130:/opt/kubernetes/ssl/ flanneld-key.pem 100% 1675 291.1KB/s 00:00 flanneld.pem 100% 1391 90.4KB/s 00:00 (4)下载Flannel软件包 [root@linux-node1 ~]# cd /usr/local/src # wget https://github.com/coreos/flannel/releases/download/v0.10.0/flannel-v0.10.0-linux-amd64.tar.gz [root@linux-node1 src]# tar zxf flannel-v0.10.0-linux-amd64.tar.gz [root@linux-node1 src]# cp flanneld mk-docker-opts.sh /opt/kubernetes/bin/ 复制到linux-node2和linux-node3节点 [root@linux-node1 src]# scp flanneld mk-docker-opts.sh 192.168.56.120:/opt/kubernetes/bin/ [root@linux-node1 src]# scp flanneld mk-docker-opts.sh 192.168.56.130:/opt/kubernetes/bin/ 复制对应脚本到/opt/kubernetes/bin目录下。 [root@linux-node1 ~]# cd /usr/local/src/kubernetes/cluster/centos/node/bin/ [root@linux-node1 bin]# cp remove-docker0.sh /opt/kubernetes/bin/ [root@linux-node1 bin]# scp remove-docker0.sh 192.168.56.120:/opt/kubernetes/bin/ [root@linux-node1 bin]# scp remove-docker0.sh 192.168.56.130:/opt/kubernetes/bin/ (5)配置Flannel [root@linux-node1 ~]# vim /opt/kubernetes/cfg/flannel FLANNEL_ETCD="-etcd-endpoints=https://192.168.56.110:2379,https://192.168.56.120:2379,https://192.168.56.130:2379" FLANNEL_ETCD_KEY="-etcd-prefix=/kubernetes/network" FLANNEL_ETCD_CAFILE="--etcd-cafile=/opt/kubernetes/ssl/ca.pem" FLANNEL_ETCD_CERTFILE="--etcd-certfile=/opt/kubernetes/ssl/flanneld.pem" FLANNEL_ETCD_KEYFILE="--etcd-keyfile=/opt/kubernetes/ssl/flanneld-key.pem" 复制配置到其它节点上 [root@linux-node1 ~]# scp /opt/kubernetes/cfg/flannel 192.168.56.120:/opt/kubernetes/cfg/ [root@linux-node1 ~]# scp /opt/kubernetes/cfg/flannel 192.168.56.130:/opt/kubernetes/cfg/ (6)设置Flannel系统服务 [root@linux-node1 ~]# vim /usr/lib/systemd/system/flannel.service [Unit] Description=Flanneld overlay address etcd agent After=network.target Before=docker.service [Service] EnvironmentFile=-/opt/kubernetes/cfg/flannel ExecStartPre=/opt/kubernetes/bin/remove-docker0.sh ExecStart=/opt/kubernetes/bin/flanneld ${FLANNEL_ETCD} ${FLANNEL_ETCD_KEY} ${FLANNEL_ETCD_CAFILE} ${FLANNEL_ETCD_CERTFILE} ${FLANNEL_ETCD_KEYFILE} ExecStartPost=/opt/kubernetes/bin/mk-docker-opts.sh -d /run/flannel/docker Type=notify [Install] WantedBy=multi-user.target RequiredBy=docker.service 复制系统服务脚本到其它节点上 # scp /usr/lib/systemd/system/flannel.service 192.168.56.120:/usr/lib/systemd/system/ # scp /usr/lib/systemd/system/flannel.service 192.168.56.130:/usr/lib/systemd/system/ 三、Flannel CNI集成 (1)下载CNI插件 https://github.com/containernetworking/plugins/releases wget https://github.com/containernetworking/plugins/releases/download/v0.7.1/cni-plugins-amd64-v0.7.1.tgz [root@linux-node1 ~]# mkdir /opt/kubernetes/bin/cni [root@linux-node2 ~]# mkdir /opt/kubernetes/bin/cni [root@linux-node3 ~]# mkdir /opt/kubernetes/bin/cni [root@linux-node1 src]# tar zxf cni-plugins-amd64-v0.7.1.tgz -C /opt/kubernetes/bin/cni [root@linux-node1 src]# scp -r /opt/kubernetes/bin/cni/* 192.168.56.120:/opt/kubernetes/bin/cni/ [root@linux-node1 src]# scp -r /opt/kubernetes/bin/cni/* 192.168.56.130:/opt/kubernetes/bin/cni/ (2)创建Etcd的key 此步的操作是为了创建POD的网段,并在ETCD中存储,而后FLANNEL从ETCD中取出并进行分配 ...

August 15, 2018

k8s学习笔记-04-Node节点二进制部署

[TOC] K8S Node节点部署 1、部署kubelet (1)二进制包准备 [root@linux-node1 ~]# cd /usr/local/src/kubernetes/server/bin/ [root@linux-node1 bin]# cp kubelet kube-proxy /opt/kubernetes/bin/ [root@linux-node1 bin]# scp kubelet kube-proxy 192.168.56.120:/opt/kubernetes/bin/ [root@linux-node1 bin]# scp kubelet kube-proxy 192.168.56.130:/opt/kubernetes/bin/ (2)创建角色绑定 kubelet启动时会向kube-apiserver发送tsl bootstrap请求,所以需要将bootstrap的token设置成对应的角色,这样kubectl才有权限创建该请求。 [root@linux-node1 ~]# kubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --user=kubelet-bootstrap clusterrolebinding "kubelet-bootstrap" created (3)创建 kubelet bootstrapping kubeconfig 文件 设置集群参数 [root@linux-node1 ~]# cd /usr/local/src/ssl [root@linux-node1 ssl]# kubectl config set-cluster kubernetes \ --certificate-authority=/opt/kubernetes/ssl/ca.pem \ --embed-certs=true \ --server=https://192.168.56.110:6443 \ --kubeconfig=bootstrap.kubeconfig Cluster "kubernetes" set. (4)设置客户端认证参数 [root@linux-node1 ssl]# kubectl config set-credentials kubelet-bootstrap \ --token=ad6d5bb607a186796d8861557df0d17f \ --kubeconfig=bootstrap.kubeconfig User "kubelet-bootstrap" set. (5)设置上下文参数 [root@linux-node1 ssl]# kubectl config set-context default \ --cluster=kubernetes \ --user=kubelet-bootstrap \ --kubeconfig=bootstrap.kubeconfig Context "default" created. (6)选择默认上下文 [root@linux-node1 ssl]# kubectl config use-context default --kubeconfig=bootstrap.kubeconfig Switched to context "default". [root@linux-node1 ssl]# cp bootstrap.kubeconfig /opt/kubernetes/cfg [root@linux-node1 ssl]# scp bootstrap.kubeconfig 192.168.56.120:/opt/kubernetes/cfg [root@linux-node1 ssl]# scp bootstrap.kubeconfig 192.168.56.130:/opt/kubernetes/cfg 2、部署kubelete 1.设置CNI支持 (1)配置CNI [root@linux-node2 ~]# mkdir -p /etc/cni/net.d [root@linux-node2 ~]# vim /etc/cni/net.d/10-default.conf { "name": "flannel", "type": "flannel", "delegate": { "bridge": "docker0", "isDefaultGateway": true, "mtu": 1400 } } [root@linux-node3 ~]# mkdir -p /etc/cni/net.d [root@linux-node2 ~]# scp /etc/cni/net.d/10-default.conf 192.168.56.130:/etc/cni/net.d/10-default.conf (2)创建kubelet数据存储目录 [root@linux-node2 ~]# mkdir /var/lib/kubelet [root@linux-node3 ~]# mkdir /var/lib/kubelet (3)创建kubelet服务配置 [root@linux-node2 ~]# vim /usr/lib/systemd/system/kubelet.service [Unit] Description=Kubernetes Kubelet Documentation=https://github.com/GoogleCloudPlatform/kubernetes After=docker.service Requires=docker.service [Service] WorkingDirectory=/var/lib/kubelet ExecStart=/opt/kubernetes/bin/kubelet \ --address=192.168.56.120 \ --hostname-override=192.168.56.120 \ --pod-infra-container-image=mirrorgooglecontainers/pause-amd64:3.0 \ --experimental-bootstrap-kubeconfig=/opt/kubernetes/cfg/bootstrap.kubeconfig \ --kubeconfig=/opt/kubernetes/cfg/kubelet.kubeconfig \ --cert-dir=/opt/kubernetes/ssl \ --network-plugin=cni \ --cni-conf-dir=/etc/cni/net.d \ --cni-bin-dir=/opt/kubernetes/bin/cni \ --cluster-dns=10.1.0.2 \ --cluster-domain=cluster.local. \ --hairpin-mode hairpin-veth \ --allow-privileged=true \ --fail-swap-on=false \ --logtostderr=true \ --v=2 \ --logtostderr=false \ --log-dir=/opt/kubernetes/log Restart=on-failure RestartSec=5 [root@linux-node3 ~]# vim /usr/lib/systemd/system/kubelet.service [Unit] Description=Kubernetes Kubelet Documentation=https://github.com/GoogleCloudPlatform/kubernetes After=docker.service Requires=docker.service [Service] WorkingDirectory=/var/lib/kubelet ExecStart=/opt/kubernetes/bin/kubelet \ --address=192.168.56.130 \ --hostname-override=192.168.56.130 \ --pod-infra-container-image=mirrorgooglecontainers/pause-amd64:3.0 \ --experimental-bootstrap-kubeconfig=/opt/kubernetes/cfg/bootstrap.kubeconfig \ --kubeconfig=/opt/kubernetes/cfg/kubelet.kubeconfig \ --cert-dir=/opt/kubernetes/ssl \ --network-plugin=cni \ --cni-conf-dir=/etc/cni/net.d \ --cni-bin-dir=/opt/kubernetes/bin/cni \ --cluster-dns=10.1.0.2 \ --cluster-domain=cluster.local. \ --hairpin-mode hairpin-veth \ --allow-privileged=true \ --fail-swap-on=false \ --logtostderr=true \ --v=2 \ --logtostderr=false \ --log-dir=/opt/kubernetes/log Restart=on-failure RestartSec=5 (4)启动Kubelet [root@linux-node2 ~]# systemctl daemon-reload [root@linux-node2 ~]# systemctl enable kubelet [root@linux-node2 ~]# systemctl start kubelet [root@linux-node2 kubernetes]# systemctl status kubelet [root@linux-node3 ~]# systemctl daemon-reload [root@linux-node3 ~]# systemctl enable kubelet [root@linux-node3 ~]# systemctl start kubelet [root@linux-node3 kubernetes]# systemctl status kubelet 在查看kubelet的状态,发现有如下报错Failed to get system container stats for "/system.slice/kubelet.service": failed to...此时需要调整kubelet的启动参数。 ...

August 14, 2018