k8s学习笔记-19-Kubernetes dashboard认证访问

[TOC] Dashboard:https://github.com/kubernetes/dashboard 一、Dashboard部署 由于需要用到k8s.gcr.io/kubernetes-dashboard-amd64:v1.10.0,这里有2种方式进行pull 镜像。docker search该镜像名称,直接pull,再重新进行tag;另外一种方式是通过谷歌容器镜像拉取。 [root@k8s-node01 ~]# docker pull siriuszg/kubernetes-dashboard-amd64 [root@k8s-node01 ~]# docker tag siriuszg/kubernetes-dashboard-amd64:latest k8s.gcr.io/kubernetes-dashboard-amd64:v1.10.0 或者是 [root@k8s-node01 ~]# docker pull mirrorgooglecontainers/kubernetes-dashboard-amd64:v1.10.0 再看其部署的过程: [root@k8s-master ~]# kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/recommended/kubernetes-dashboard.yaml secret/kubernetes-dashboard-certs created serviceaccount/kubernetes-dashboard created role.rbac.authorization.k8s.io/kubernetes-dashboard-minimal created rolebinding.rbac.authorization.k8s.io/kubernetes-dashboard-minimal created deployment.apps/kubernetes-dashboard created service/kubernetes-dashboard created [root@k8s-master ~]# kubectl get pods -n kube-system NAME READY STATUS RESTARTS AGE coredns-78fcdf6894-nmcmz 1/1 Running 1 54d coredns-78fcdf6894-p5pfm 1/1 Running 1 54d etcd-k8s-master 1/1 Running 2 54d kube-apiserver-k8s-master 1/1 Running 9 54d kube-controller-manager-k8s-master 1/1 Running 5 54d kube-flannel-ds-n5c86 1/1 Running 1 54d kube-flannel-ds-nrcw2 1/1 Running 1 52d kube-flannel-ds-pgpr7 1/1 Running 5 54d kube-proxy-glzth 1/1 Running 1 52d kube-proxy-rxlt7 1/1 Running 2 54d kube-proxy-vxckf 1/1 Running 4 54d kube-scheduler-k8s-master 1/1 Running 3 54d kubernetes-dashboard-767dc7d4d-n4clq 1/1 Running 0 3s [root@k8s-master ~]# kubectl get svc -n kube-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP 54d kubernetes-dashboard ClusterIP 10.105.204.4 <none> 443/TCP 30m [root@k8s-master ~]# kubectl patch svc kubernetes-dashboard -p '{"spec":{"type":"NodePort"}}' -n kube-system #以打补丁方式修改dasboard的访问方式 service/kubernetes-dashboard patched [root@k8s-master ~]# kubectl get svc -n kube-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP 54d kubernetes-dashboard NodePort 10.105.204.4 <none> 443:32645/TCP 31m 浏览器访问:https://192.168.56.12:32645,如图:这里需要注意的是谷歌浏览器会禁止不安全证书访问,建议使用火狐浏览器,并且需要在高级选项中添加信任 ...

September 10, 2018

k8s学习笔记-18-认证、授权和准入控制

[TOC] API Server作为Kubernetes网关,是访问和管理资源对象的唯一入口,其各种集群组件访问资源都需要经过网关才能进行正常访问和管理。每一次的访问请求都需要进行合法性的检验,其中包括身份验证、操作权限验证以及操作规范验证等,需要通过一系列验证通过之后才能访问或者存储数据到etcd当中。如下图: 一、ServiceAccount Service account是为了方便Pod里面的进程调用Kubernetes API或其他外部服务而设计的。它与User account不同 User account是为人设计的,而service account则是为Pod中的进程调用Kubernetes API而设计; User account是跨namespace的,而service account则是仅局限它所在的namespace; 每个namespace都会自动创建一个default service account Token controller检测service account的创建,并为它们创建secret 开启ServiceAccount Admission Controller后 每个Pod在创建后都会自动设置spec.serviceAccount为default(除非指定了其他ServiceAccout) 验证Pod引用的service account已经存在,否则拒绝创建 如果Pod没有指定ImagePullSecrets,则把service account的ImagePullSecrets加到Pod中 每个container启动后都会挂载该service account的token和ca.crt到/var/run/secrets/kubernetes.io/serviceaccount/ 当创建 pod 的时候,如果没有指定一个 service account,系统会自动在与该pod 相同的 namespace 下为其指派一个default service account。而pod和apiserver之间进行通信的账号,称为serviceAccountName。如下: [root@k8s-master ~]# kubectl get pods NAME READY STATUS RESTARTS AGE filebeat-ds-hxgdx 1/1 Running 1 34d filebeat-ds-s466l 1/1 Running 2 34d myapp-0 1/1 Running 0 3h myapp-1 1/1 Running 0 3h myapp-2 1/1 Running 0 4h myapp-3 1/1 Running 0 4h pod-vol-demo 2/2 Running 0 2d redis-5b5d6fbbbd-q8ppz 1/1 Running 1 2d [root@k8s-master ~]# kubectl get pods/myapp-0 -o yaml |grep "serviceAccountName" serviceAccountName: default [root@k8s-master ~]# kubectl describe pods myapp-0 Name: myapp-0 Namespace: default ...... Volumes: ...... default-token-j5pf5: Type: Secret (a volume populated by a Secret) SecretName: default-token-j5pf5 Optional: false 从上面可以看到每个Pod无论定义与否都会有个存储卷,这个存储卷为default-token-*** token令牌,这就是pod和serviceaccount认证信息。通过secret进行定义,由于认证信息属于敏感信息,所以需要保存在secret资源当中,并以存储卷的方式挂载到Pod当中。从而让Pod内运行的应用通过对应的secret中的信息来连接apiserver,并完成认证。每个 namespace 中都有一个默认的叫做 default 的 service account 资源。进行查看名称空间内的secret,也可以看到对应的default-token。让当前名称空间中所有的pod在连接apiserver时可以使用的预制认证信息,从而保证pod之间的通信。 ...

September 8, 2018

k8s学习笔记-17-statefulset控制器

[TOC] 一、statefulset简介 从前面的学习我们知道使用Deployment创建的pod是无状态的,当挂载了Volume之后,如果该pod挂了,Replication Controller会再启动一个pod来保证可用性,但是由于pod是无状态的,pod挂了就会和之前的Volume的关系断开,新创建的Pod无法找到之前的Pod。但是对于用户而言,他们对底层的Pod挂了是没有感知的,但是当Pod挂了之后就无法再使用之前挂载的存储卷。 为了解决这一问题,就引入了StatefulSet用于保留Pod的状态信息。 StatefulSet是为了解决有状态服务的问题(对应Deployments和ReplicaSets是为无状态服务而设计),其应用场景包括: 1、稳定的持久化存储,即Pod重新调度后还是能访问到相同的持久化数据,基于PVC来实现 2、稳定的网络标志,即Pod重新调度后其PodName和HostName不变,基于Headless Service(即没有Cluster IP的Service)来实现 3、有序部署,有序扩展,即Pod是有顺序的,在部署或者扩展的时候要依据定义的顺序依次依次进行(即从0到N-1,在下一个Pod运行之前所有之前的Pod必须都是Running和Ready状态),基于init containers来实现 4、有序收缩,有序删除(即从N-1到0) 5、有序的滚动更新 从上面的应用场景可以发现,StatefulSet由以下几个部分组成: Headless Service(无头服务)用于为Pod资源标识符生成可解析的DNS记录。 volumeClaimTemplates (存储卷申请模板)基于静态或动态PV供给方式为Pod资源提供专有的固定存储。 StatefulSet,用于管控Pod资源。 二、为什么要有headless?? 在deployment中,每一个pod是没有名称,是随机字符串,是无序的。而statefulset中是要求有序的,每一个pod的名称必须是固定的。当节点挂了,重建之后的标识符是不变的,每一个节点的节点名称是不能改变的。pod名称是作为pod识别的唯一标识符,必须保证其标识符的稳定并且唯一。 为了实现标识符的稳定,这时候就需要一个headless service 解析直达到pod,还需要给pod配置一个唯一的名称。 三、为什么要 有volumeClainTemplate?? 大部分有状态副本集都会用到持久存储,比如分布式系统来说,由于数据是不一样的,每个节点都需要自己专用的存储节点。而在deployment中pod模板中创建的存储卷是一个共享的存储卷,多个pod使用同一个存储卷,而statefulset定义中的每一个pod都不能使用同一个存储卷,由此基于pod模板创建pod是不适应的,这就需要引入volumeClainTemplate,当在使用statefulset创建pod时,会自动生成一个PVC,从而请求绑定一个PV,从而有自己专用的存储卷。Pod名称、PVC和PV关系图如下: 四、statefulSet使用演示 在创建StatefulSet之前需要准备的东西,值得注意的是创建顺序非常关键,创建顺序如下: 1、Volume 2、Persistent Volume 3、Persistent Volume Claim 4、Service 5、StatefulSet Volume可以有很多种类型,比如nfs、glusterfs等,我们这里使用的ceph RBD来创建。 (1)查看statefulset的定义 [root@k8s-master ~]# kubectl explain statefulset KIND: StatefulSet VERSION: apps/v1 DESCRIPTION: StatefulSet represents a set of pods with consistent identities. Identities are defined as: - Network: A single stable DNS and hostname. - Storage: As many VolumeClaims as requested. The StatefulSet guarantees that a given network identity will always map to the same storage identity. FIELDS: apiVersion <string> kind <string> metadata <Object> spec <Object> status <Object> [root@k8s-master ~]# kubectl explain statefulset.spec KIND: StatefulSet VERSION: apps/v1 RESOURCE: spec <Object> DESCRIPTION: Spec defines the desired identities of pods in this set. A StatefulSetSpec is the specification of a StatefulSet. FIELDS: podManagementPolicy <string> #Pod管理策略 replicas <integer> #副本数量 revisionHistoryLimit <integer> #历史版本限制 selector <Object> -required- #选择器,必选项 serviceName <string> -required- #服务名称,必选项 template <Object> -required- #模板,必选项 updateStrategy <Object> #更新策略 volumeClaimTemplates <[]Object> #存储卷申请模板,列表对象形式 (2)清单定义StatefulSet 如上所述,一个完整的StatefulSet控制器由一个Headless Service、一个StatefulSet和一个volumeClaimTemplate组成。如下资源清单中的定义: ...

September 3, 2018

k8s学习笔记-16-存储卷

[TOC] 一、存储卷的概念和类型 为了保证数据的持久性,必须保证数据在外部存储在docker容器中,为了实现数据的持久性存储,在宿主机和容器内做映射,可以保证在容器的生命周期结束,数据依旧可以实现持久性存储。但是在k8s中,由于pod分布在各个不同的节点之上,并不能实现不同节点之间持久性数据的共享,并且,在节点故障时,可能会导致数据的永久性丢失。为此,k8s就引入了外部存储卷的功能。 k8s的存储卷类型: [root@k8s-master ~]# kubectl explain pod.spec.volumes #查看k8s支持的存储类型 KIND: Pod VERSION: v1 常用分类: emptyDir(临时目录):Pod删除,数据也会被清除,这种存储成为emptyDir,用于数据的临时存储。 hostPath(宿主机目录映射): 本地的SAN(iSCSI,FC)、NAS(nfs,cifs,http)存储 分布式存储(glusterfs,rbd,cephfs) 云存储(EBS,Azure Disk) persistentVolumeClaim –>PVC(存储卷创建申请) 当你需要创建一个存储卷时,只需要进行申请对应的存储空间即可使用,这就是PVC。其关联关系如图: 上图解析:在Pod上定义一个PVC,该PVC要关联到当前名称空间的PVC资源,该PVC只是一个申请,PVC需要和PV进行关联。PV属于存储上的一部分存储空间。但是该方案存在的问题是,我们无法知道用户是什么时候去创建Pod,也不知道创建Pod时定义多大的PVC,那么如何实现按需创建呢??? 不需要PV层,把所有存储空间抽象出来,这一个抽象层称为存储类,当用户创建PVC需要用到PV时,可以向存储类申请对应的存储空间,存储类会按照需求创建对应的存储空间,这就是PV的动态供给,如图: 那么PV的动态供给,其重点是在存储类的定义,其分类大概是对存储的性能进行分类的,如图:金存储类、银存储类、铜存储类等。 总结: k8s要使用存储卷,需要2步: 1、在pod定义volume,并指明关联到哪个存储设备 2、在容器使用volume mount进行挂载 二、emptyDir存储卷演示 一个emptyDir 第一次创建是在一个pod被指定到具体node的时候,并且会一直存在在pod的生命周期当中,正如它的名字一样,它初始化是一个空的目录,pod中的容器都可以读写这个目录,这个目录可以被挂在到各个容器相同或者不相同的的路径下。当一个pod因为任何原因被移除的时候,这些数据会被永久删除。注意:一个容器崩溃了不会导致数据的丢失,因为容器的崩溃并不移除pod. emptyDir 磁盘的作用: (1)普通空间,基于磁盘的数据存储 (2)作为从崩溃中恢复的备份点 (3)存储那些那些需要长久保存的数据,例web服务中的数据 默认的,emptyDir 磁盘会存储在主机所使用的媒介上,可能是SSD,或者网络硬盘,这主要取决于你的环境。当然,我们也可以将emptyDir.medium的值设置为Memory来告诉Kubernetes 来挂在一个基于内存的目录tmpfs,因为 tmpfs速度会比硬盘块度了,但是,当主机重启的时候所有的数据都会丢失。 [root@k8s-master ~]# kubectl explain pods.spec.volumes.emptyDir #查看emptyDir存储定义 [root@k8s-master ~]# kubectl explain pods.spec.containers.volumeMounts #查看容器挂载方式 [root@k8s-master ~]# cd mainfests && mkdir volumes && cd volumes [root@k8s-master volumes]# cp ../pod-demo.yaml ./ [root@k8s-master volumes]# mv pod-demo.yaml pod-vol-demo.yaml [root@k8s-master volumes]# vim pod-vol-demo.yaml #创建emptyDir的清单 apiVersion: v1 kind: Pod metadata: name: pod-demo namespace: default labels: app: myapp tier: frontend annotations: magedu.com/create-by:"cluster admin" spec: containers: - name: myapp image: ikubernetes/myapp:v1 imagePullPolicy: IfNotPresent ports: - name: http containerPort: 80 volumeMounts: #在容器内定义挂载存储名称和挂载路径 - name: html mountPath: /usr/share/nginx/html/ - name: busybox image: busybox:latest imagePullPolicy: IfNotPresent volumeMounts: - name: html mountPath: /data/ #在容器内定义挂载存储名称和挂载路径 command: ['/bin/sh','-c','while true;do echo $(date) >> /data/index.html;sleep 2;done'] volumes: #定义存储卷 - name: html #定义存储卷名称 emptyDir: {} #定义存储卷类型 [root@k8s-master volumes]# kubectl apply -f pod-vol-demo.yaml pod/pod-vol-demo created [root@k8s-master volumes]# kubectl get pods NAME READY STATUS RESTARTS AGE pod-vol-demo 2/2 Running 0 27s [root@k8s-master volumes]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE ...... pod-vol-demo 2/2 Running 0 16s 10.244.2.34 k8s-node02 ...... 在上面,我们定义了2个容器,其中一个容器是输入日期到index.html中,然后验证访问nginx的html是否可以获取日期。以验证两个容器之间挂载的emptyDir实现共享。如下访问验证: [root@k8s-master volumes]# curl 10.244.2.34 #访问验证 Tue Oct 9 03:56:53 UTC 2018 Tue Oct 9 03:56:55 UTC 2018 Tue Oct 9 03:56:57 UTC 2018 Tue Oct 9 03:56:59 UTC 2018 Tue Oct 9 03:57:01 UTC 2018 Tue Oct 9 03:57:03 UTC 2018 Tue Oct 9 03:57:05 UTC 2018 Tue Oct 9 03:57:07 UTC 2018 Tue Oct 9 03:57:09 UTC 2018 Tue Oct 9 03:57:11 UTC 2018 Tue Oct 9 03:57:13 UTC 2018 Tue Oct 9 03:57:15 UTC 2018 三、hostPath存储卷演示 hostPath宿主机路径,就是把pod所在的宿主机之上的脱离pod中的容器名称空间的之外的宿主机的文件系统的某一目录和pod建立关联关系,在pod删除时,存储数据不会丢失。 ...

September 2, 2018

k8s学习笔记-15-Ingress和Ingress Controller

[TOC] 一、什么是Ingress? 从前面的学习,我们可以了解到Kubernetes暴露服务的方式目前只有三种:LoadBlancer Service、ExternalName、NodePort Service、Ingress;而我们需要将集群内服务提供外界访问就会产生以下几个问题: 1、Pod 漂移问题 Kubernetes 具有强大的副本控制能力,能保证在任意副本(Pod)挂掉时自动从其他机器启动一个新的,还可以动态扩容等,通俗地说,这个 Pod 可能在任何时刻出现在任何节点上,也可能在任何时刻死在任何节点上;那么自然随着 Pod 的创建和销毁,Pod IP 肯定会动态变化;那么如何把这个动态的 Pod IP 暴露出去?这里借助于 Kubernetes 的 Service 机制,Service 可以以标签的形式选定一组带有指定标签的 Pod,并监控和自动负载他们的 Pod IP,那么我们向外暴露只暴露 Service IP 就行了;这就是 NodePort 模式:即在每个节点上开起一个端口,然后转发到内部 Pod IP 上,如下图所示: 此时的访问方式:http://nodeip:nodeport/ 2、端口管理问题 采用 NodePort 方式暴露服务面临问题是,服务一旦多起来,NodePort 在每个节点上开启的端口会及其庞大,而且难以维护;这时,我们可以能否使用一个Nginx直接对内进行转发呢?众所周知的是,Pod与Pod之间是可以互相通信的,而Pod是可以共享宿主机的网络名称空间的,也就是说当在共享网络名称空间时,Pod上所监听的就是Node上的端口。那么这又该如何实现呢?简单的实现就是使用 DaemonSet 在每个 Node 上监听 80,然后写好规则,因为 Nginx 外面绑定了宿主机 80 端口(就像 NodePort),本身又在集群内,那么向后直接转发到相应 Service IP 就行了,如下图所示: 3、域名分配及动态更新问题 从上面的方法,采用 Nginx-Pod 似乎已经解决了问题,但是其实这里面有一个很大缺陷:当每次有新服务加入又该如何修改 Nginx 配置呢??我们知道使用Nginx可以通过虚拟主机域名进行区分不同的服务,而每个服务通过upstream进行定义不同的负载均衡池,再加上location进行负载均衡的反向代理,在日常使用中只需要修改nginx.conf即可实现,那在K8S中又该如何实现这种方式的调度呢??? 假设后端的服务初始服务只有ecshop,后面增加了bbs和member服务,那么又该如何将这2个服务加入到Nginx-Pod进行调度呢?总不能每次手动改或者Rolling Update 前端 Nginx Pod 吧!!此时 Ingress 出现了,如果不算上面的Nginx,Ingress 包含两大组件:Ingress Controller 和 Ingress。 ...

September 1, 2018

k8s学习笔记-13-Pod控制器--DaemonSet

[TOC] 一、什么是DaemonSet? DaemonSet 确保全部(或者一些)Node 上运行一个 Pod 的副本。当有 Node 加入集群时,也会为他们新增一个 Pod 。当有 Node 从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod。 使用 DaemonSet 的一些典型用法: 运行集群存储 daemon,例如在每个 Node 上运行 glusterd、ceph。 在每个 Node 上运行日志收集 daemon,例如fluentd、logstash。 在每个 Node 上运行监控 daemon,例如 Prometheus Node Exporter、collectd、Datadog 代理、New Relic 代理,或 Ganglia gmond。 一个简单的用法是,在所有的 Node 上都存在一个 DaemonSet,将被作为每种类型的 daemon 使用。 一个稍微复杂的用法可能是,对单独的每种类型的 daemon 使用多个 DaemonSet,但具有不同的标志,和/或对不同硬件类型具有不同的内存、CPU要求。 二、编写DaemonSet Spec (1)必需字段 和其它所有 Kubernetes 配置一样,DaemonSet 需要 apiVersion、kind 和 metadata字段。 [root@k8s-master ~]# kubectl explain daemonset KIND: DaemonSet VERSION: extensions/v1beta1 DESCRIPTION: DEPRECATED - This group version of DaemonSet is deprecated by apps/v1beta2/DaemonSet. See the release notes for more information. DaemonSet represents the configuration of a daemon set. FIELDS: apiVersion <string> APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources kind <string> Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds metadata <Object> Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata spec <Object> The desired behavior of this daemon set. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status status <Object> The current status of this daemon set. This data may be out of date by some window of time. Populated by the system. Read-only. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status (2)Pod模板 ...

August 29, 2018

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