一,概述

1,简介

2014年,谷歌发布了kubernetes开源项目,作用包括自动化容器应用程序的部署、扩展和管理。它通常和docker一起使用,并且整合多个运行着docker容器的主机集群。致力于让部署容器化的应用简单而高效。核心是能够自主管理容器来保证云平台的容器按照用户的期望运行。官网介绍,k8s的主要特性有:自动包装;横向缩放;自动保护署和回滚;存储编排;自我修复。目前,它是一个较新的基于容器技术的分布式框架方案;无侵入性,具有开放性;具有完备的分布式系统支撑平台。提供一个以容器为中心的基础架构。可以满足的场景有:多个进程协同工作;存储系统挂载;分布式秘钥;应用健康检测;应用实例的复制;pod自动伸缩扩展;命名发现;负载均衡;滚动更新。

2,入门

1),准备环境

连接linux主机

关闭防火墙

systemctl  disable  firewalld

systemctl  stop  firewalld

安装etc和kubernetes

yum  install  -y  etcd  kubernetes

启动k8s服务

systemctl  start  etcd

systemctl  start  docker

systemctl  start  kube-apiserver

systemctl  start  kube-controller-manager

systemctl  start  kube-scheduler

systemctl  start  kubelet

systemctl  start  kube-proxy

如果docker启动失败,可以vi  /etc/sysconfig/selinux  将selunux后的值改为disable,重启服务器,重启docker。

2),添加配置文件

在usr/local下新建k8s目录,添加tomcat配置文件mytomat.rc.yaml

 

apiVersion: v1

kind: ReplicationController

metadata:

 name: mytomcat

spec:

 replicas: 2

 selector:

  app: mytomcat

 template:

  metadata:

   labels:

    app: mytomcat

  spec:

    containers:

     - name: mytomcat

       image: tomcat:7-jre7

       ports:

       - containerPort: 8080

 

注意-后面有一个空格。

执行kubectl  create  -f  mytomcat.rc.yaml创建容器mytomcat。

添加配置文件mytomcat.svc.yaml

apiVersion: v1

kind: Service

metadata:

 name: mytomcat

spec:

 type: NodePort

 ports:

  - port: 8080

   nodePort: 30001

 selector:

  app: mytomcat

 

执行kubectl  create  -f  mytomcat.svc.yaml创建服务mytomcat

执行kubectl  get  svc查看创建的服务。

3),可能遇到的问题

执行kubectl  get  pods获取容器失败的解决方法:vi  /etc/kubernetes/apiserver,找到KUBE_ADMISSION_CONTROL="--admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota",去掉ServiceAccount。重启kube-apiserver,systemctl  restart  kube-apiserver。

Pod节点中容器启动失败,可能是因为docker  pull失败。两种解决方案:

首先

yum  install  *rhsm*

docker  pull  registry.access.redhat.com/rhel7/pod-infrastructure:latest

如果pull失败,可以尝试,先,wget  http://mirror.centos.org/centos/7/os/x86_64/Packages/python-rhsm-certificates-1.19.10-1.el7_4.x86_64.rpm;然后,rpm2cpio  python-rhsm-certificates-1.19.10-1.el7_4.x86_64.rpm  |  cpio  -iv --to-stdout  ./etc/rhsm/ca/redhat-uep.pem  |  tee  /etc/rhsm/ca/redhat-uep.pem   ,然后,在pull,docker  pull  registry.access.redhat.com/rhel7/pod-infrastructure:latest

如果执行这两个步骤后,问题解决,可以不用执行下面步骤。

下面两个方案中选择一个。

方案1:

docker  search  pod-infrastructure

docker  pull  docker.io/xxxxx/pod-infrastructure

docker  tag  xxxxx /pod-infrastructure  192.168.253.128:5000/pod-infrastructure

docker  push  192.168.253.128:5000/pod-infrastructure

vi  /etc/kubernetes/kubelet

修改

KUBELET_POD_INFRA_CONTAINER="--pod-infra-container-image=192.168.126.143:5000/pod-infrastructure:latest"。

重启服务:

systemctl  restart  kube-apiserve

systemctl  restart  kube-controller-manager

systemctl  restart  kube-scheduler  

systemctl  restart  kubelet  

systemctl  restart  kube-proxy

方案2:

docker  pull  kubernetes/pause

docker  tag  docker.io/kubernetes/pause:latest  192.168.253.128:5000/google_containers/pause-amd64.3.0

docker  push  192.168.253.128:5000/google_containers/pause-amd64.3.0

如果pushPut http://192.168.253.128:5000/v1/repositories/google_containers/pause-amd64.3.0/: dial tcp 192.168.253.128:5000: connect: connection refused,首先查看dockerregister容器是否启动(docker  ps  -a查看registerSTATUS是否为UP),如果register启动,查看在/etc/docker/下面的几个daemon文件中是否设置:

{ "insecure-registries":["10.200.10.10:5000"] }。如果没有设置需要设置,然后

systemctl  daemon-reload

systemctl  restart  docker

然后,重新尝试push
vi  /etc/kubernetes/kubelet修改配置:

KUBELET_ARGS="--pod_infra_container_image=192.168.253.128:5000/google_containers/pause-amd64.3.0"

重启kubelet服务器systemctl  restart  kubelet。重新执行kubectl  get  pod查看是否启动成功。

如果还是启动失败,执行kubectl  describe  pod  podname查看执行记录,一般是拉取镜像问题。

浏览器访问http://192.168.253.128:30001/。如果是外网访问失败,因为k8s的容器,只能在其所在的节点上curl访问,对于其他主机无法访问,解决方案是:vi  /etc/sysctl.conf,修改net.ipv4.ip_forward=1。如果还是不能访问,可能是iptables的原因,可以设置iptables的过滤规则为通过:iptables  -P  FORWARD  ACCEPT,这个设置表示处理转发包的策略为允许通过。

3,基本架构

K8s集群包含有节点代理kubelet和master组件,基于分布式存储系统。节点可以运行应用容器,且受到master的控制。每个节点上都要运行docker,docker来负责所有具体的影响下载和容器运行。

K8s的核心组件包括:etcd保存了整个集群的状态;apiserver提供了资源操作的唯一入口,提供认证、授权、访问控制、api注册和发现等机制;controller manager负责维护集群的状态,比如故障检测、自动扩展、滚动更新等;sheduler负责资源的调度,按照预定的调度策略将pod调度到相应的机器上;kubelet负责维护容器的生命周期,同时也负责volume和网络的管理;container runtime负责镜像管理以及pod和容器的真正运行;kube-proxy负责为service提供cluster内部的服务发现和负载均衡。此外,还有一些可选的add-ons,kube-dns负责整个集群的dns服务;ingress controller为服务提供外网入口;heapster提供资源监控;dashboard提供gui;federation提供跨可用区的集群;fluentd-elasticsearch提供集群日志采集、存储与查询。

K8s设计理念和功能分层类似一个lunux分层架构。包括:

核心层,提供api构建高层的应用,对内提供插件式应用执行环境;应用层,负责部署(无状态应用、有状态应用、批处理任务、集群应用)和路由(服务发现,dns解析);管理层,系统度量(基础设施、容器、网络度量),自动化(自动扩展,动态provision)以及策略管理(RBAC、quota、psp、networkPolicy);接口层:kubectl命令行工具、客户端SDK以及集群联邦;生态系统,在接口层之上的庞大容器集群管理调度的生态系统、可以划分为两个范畴,外部,日志、监控、配置管理、CI、CD、workflow、faas、ots应用、chatops等,内部,CRI、CNI、CVI、镜像仓库、cloud provider、集群的配置和管理。

Cluster是计算、存储和网络资源的集合、kubernetes利用cluster运行各种基于容器的应用。Cluster由master和node组成,node上运行服务。Master主要负责调度,决定应用放在哪运行。Master运行linux提供,可以是物理机或虚拟机。Master是k8s的cluster的核心,运行这daemon服务,包括kube-apiserver、kube-scheluger、kube-controller-manger、etcd和pod网路。

Etcd负责保存k8scluster的配置信息和各种资源的状态信息,当数据发生变化时,etcd会快速通知k8s相关组件。Pod网络,要能够相互通信,k8s  cluster必须部署pod网络。可以使用flannel方案。

除了master,k8s集群中的其他机器被称为node节点。Node负责运行容器应用,node由master管理。Node负责监控并汇报容器的状态,同时根据master的要求管理容器的生命周期。Node也运行在linux系统,物理机或者虚拟机。每个node运行这些关键进程,kubelet负责pod对应的容器的创建、启动等任务,同时与master节点密切协作,实现集群管理的基本功能;kube-proxy实现k8s的通信与负载均衡机制的重要组件;docker enginer,docker引擎,负责本机的容器创建和管理工作。

Pod是k8s最小单元,最重要和最基本的概念。每一个pod包含一个或多个容器,pod容器会作为一个整体被master调度到一node上运行。K8s为每个node分配了唯一的ip地址,称为podid,一个pod里的多个容器共享podid地址。一个pod里的容器与另外主机上的pod容器能够直接通信。

K8s service定义了外界访问一组特定pod的方式,service有自己的ip和端口,service为pod提供了负载均衡。它也是k8s最核心的资源对象之一,每个service其实就是一个微服务。

Replication  controller(rc)是k8s系统的核心之一,定义了一个期望的场景,声明某种pod的副本数量在任意时刻都符合某个预期值。包含了,pod启动的副本数(replicas),用于筛选目标pod的label selector,当pod的副本数量小于预期数量时,用于创建新pod的pod模板(template)。通过定义一个rc实现pod创建过程和副本数量的自动控制;rc里包括完整的pod定义模板;rc通过label selector机制实现对pod副本的自动控制;通过改变rc里的pod副本数量,可以实现pod的扩容或缩容功能;通过改变rc里pod模板中镜像版本,可以实现pod的滚动升级功能。

二,K8s集群

K8s用于协调高度可用的计算机集群,这些计算机连接作为工作单元。K8s在一个集群上以更有效的方式自动分发和调度容器应用程序。K8s集群有两种类型的资源组成:master是集群的调度节点;nodes是应用程序实际运行的工作节点。K8s集群部署的方式:kubeadm,minikube和二进制包。前两个是自动部署,简化部署操作。

1,准备工作

准备3台虚拟机。

Master                     128                etcd、kube-apiserver、kube-controller-manager、kube-scheduler、docker、kubectl

Node1                     129                kube-proxy、kubelet、docker

Node2                     130                kube-proxy、kubelet、docker

关闭所有虚拟机的防火前,firewall-cmd  --status查看防火墙状态,systemctl  stop  firewalld.service,禁止防火墙开机启动,systemctl  disable  firewalld.service。

获取k8s二进制包:

https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.9.md

master节点需要安装下述2,3,4,5,6点中的服务。

Node节点需要安装2,7,8点中的服务。

2,安装docker

更新yum

yum  update

设置yum源

vi  /etc/yum.repos.d/docker.repo

设置:

[dockerrepo]

name=Docker  Repository

baseurl=https://yum.dockerproject.org/repo/main/centos/$releasever/

enabled=1

gpgcheck=1

gpgkey=https://yum.dockerproject.org/gpg

 

安装docker

yum  install  docker-engine

如果不能安装,尝试,先删除docker.repo,然后导入key

rpm --import https://keyserver.ubuntu.com/pks/lookup?op=get&search=0xee6d536cf7dc86e2d7d56f59a178ac6c6238f52e

然后

yum-config-manager --add-repo https://packages.docker.com/1.13/yum/repo/main/centos/7

然后:yum -y install docker-engine

查看docker版本

docker  -v

3,安装etcd

Etcd是k8s集群的主要服务。下载etcd二进制文件https://github.com/etcd-io/etcd/releases。在/home/k8s下解压文件,让后cd进入文件夹,复制etcd和etcdctl到usr/bin/目录。cp  etcd  etcdctl  /usr/bin。创建服务文件:vi /usr/lib/systemd/system/etcd.service

[Service]

Type=simple

EnvironmentFile=-/etc/etcd/etcd.conf

WorkingDirectory=/var/lib/etcd/

ExecStart=/usr/bin/etcd

Restart=on-failure

[install]

WantedBy=multi-user.target

 

创建工作目录:mkdir  /var/lib/etcd/

启动etcd服务

systemctl  daemon-reload

systemctl  enable  etcd.service

mkdir  -p  /var/lib/etcd/

systemctl  start  etcd.service

检查集群健康状态,etcdctl endpoint health(etcdctl  cluster-health,3.4之前用这个命令)

4,安装kubenertes-apiserver服务

解压从github下载的kubenertes-server压缩包,将kube-apiserver、kube-controller-manager、kube-scheduler以及管理要使用的kubectl二进制命令文件放到/usr/bin目录,就完成了这几个服务的安装。

解压后,cd  kubenertes/server/bin,cp kube-apiserver kube-controller-manager kube-scheduler /usr/bin/

创建kube-apiserver的启动文件,vi  /usr/lib/systemd/system/kube-apiserver.service

[Unit]

Description=Kubernetes API Server

Documentation=https://github.com/kubernetes/kubernetes

After=etcd.service

Wants=etcd.service

[Service]

EnvironmentFile=/etc/kubernetes/apiserver

ExecStart=/usr/bin/kube-apiserver $KUBE_API_ARGS

Restart=on-failure

Type=notify

[Install]

WantedBy=multi-user.target

 

创建配置文件目录:mkdir  /etc/kubernetes,创建配置文件vi  /etc/kubernetes/apiserver

KUBE_API_ARGS="--storage-backend=etcd3 --etcd-servers=http://127.0.0.1:2379 --insecure-bind-address=0.0.0.0 --insecure-port=8080  --service-cluster-ip-range=169.169.0.0/16  --service-node-port-range=1-65535  --admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,DefaultStorageClass,ResourceQuota  --logtostderr=true  --log-dir=/var/log/kubernetes --v=2"

5,安装kube-controller-manager服务

Kube-controller-manager依赖于kube-apiserver。配置systemctl服务文件:vi  /usr/lib/systemd/system/kube-controller-manager.service

[Unit]

Description=Kubernetes Controller Manager

Documentation=https://github.com/GoogleCloudPlatform/kubernetes

After=kube-apiserver.service

Requires=kube-apiserver.service

[Service]

EnvironmentFile=-/etc/kubernetes/controller-manager

ExecStart=/usr/bin/kube-controller-manager $KUBE_CONTROLLER_MANAGER_ARGS

Restart=on-failure

LimitNOFILE=65536

[Install]

WantedBy=multi-user.target

 

创建配置文件vi  /etc/kubernetes/controller-manager

KUBE_CONTROLLER_MANAGER_ARGS="--master=http://192.168.253.129:8080 --logtostderr=true --log-dir=/var/log/kubernetes  --v=2"

注意修改ip地址为本机地址。

6,安装kube-scheduler服务

Kube-scheduler依赖于kube-apiserver服务。

配置systemd服务文件,vi /usr/lib/systemd/system/kube-scheduler.service

[Unit]

Description=Kubernetes Scheduler

Documentation=https://github.com/GoogleCloudPlatform/kubernetes

After=kube-apiserver.service

Requires=kube-apiserver.service

[Service]

EnvironmentFile=-/etc/kubernetes/scheduler

ExecStart=/usr/bin/kube-scheduler $KUBE_SCHEDULER_ARGS

Restart=on-failure

LimitNOFILE=65536

[Install]

WantedBy=multi-user.target

 

配置文件,vi /etc/kubernetes/scheduler

KUBE_SCHEDULER_ARGS="--master=http://192.168.253.129:8080 --logtostderr=true  --log-dir=/var/log/kubernetes  --v=2"

7,启动服务

 

systemctl daemon-reload

systemctl enable docker

systemctl start docker

systemctl status docker

systemctl enable kube-apiserver.service

systemctl start kube-apiserver.service

systemctl status kube-apiserver

systemctl enable kube-controller-manager

systemctl start kube-controller-manager

systemctl status kube-controller-manager

systemctl enable kube-scheduler

systemctl start kube-scheduler

systemctl status kube-scheduler

8,Node节点的安装

按照上述方式安装docker,如果由于网络原因失败,可以先从镜像下载下来,再安装。

wget https://mirrors.aliyun.com/docker-ce/linux/centos/7/x86_64/stable/Packages/docker-ce-17.12.1.ce-1.el7.centos.x86_64.rpm

yum  list|grep  docker

yum  install docker-ce-17.12.1.ce-1.el7.centos.x86_64.rpm

systemctl  enable  docker

将kubernetes-server二进制下载到node1节点。

安装kube-proxy和kubectl,cd  /home/k8s/kubernetes/server/bin。

复制kube-proxy和kubectl到/usr/bin。cp  kubectl  kube-proxy  /usr/bin/。

创建kubectl的服务文件。vi  /usr/lib/systemd/system/kubelet.service

[Unit]

Description=Kubernetes Kubelet Server

Documentation=https://github.com/GoogleCloudPlatform/kubernetes

After=docker.service

Requires=docker.service

[Service]

WorkingDirectory=/var/lib/kubelet

EnvironmentFile=-/etc/kubernetes/kubelet

ExecStart=/usr/bin/kubelet $KUBELET_ARGS

Restart=on-failure

KillMode=process

[Install]

WantedBy=multi-user.target

 

创建工作目录,mkdir /var/lib/kubelet。

创建配置文件mkdir  /etc/kubernetes,  vi  /etc/kubernetes/kubelet

KUBELET_ARGS="--kubeconfig=/etc/kubernetes/kubeconfig  --hostname-override=192.168.253.130  --logtostderr=false  --log-dir=/var/log/kubernetes  --v=2  --

fail-swap-on=false --cgroup-driver=systemd"

配置用于kubelet连接master  apiserver的配置文件。vi  /etc/kubernetes/kubeconfig

apiVersion: v1

kind: Config

clusters:

- cluster:

   server: http://192.168.253.129:8080

  name: local

contexts:

- context:

   cluster: local

  name:mycontext

current-context: mycontext

 

kube-proxy依赖于network。安装kube-proxy,需要保证network服务正常。

启动network服务,service  network  start,network启动失败的一般原因:

a.和NetworkManager服务有冲突,关闭NetworkManger服务,service NetworkManager stop,并且禁止开机启动chkconfig  NetworkManager  off。之后重启network。

b.和配置文件的MAC地址不匹配,这个也好解决,使用ipaddr(或ifconfig)查看mac地址,将/etc/sysconfig/network-scripts/ifcfg-xxx中的HWADDR改为查看到的mac地址

c.设定开机启动一个名为NetworkManager-wait-online服务,命令为:

systemctlenableNetworkManager-wait-online.service

d.查看/etc/sysconfig/network-scripts下,将其余无关的网卡位置文件全删掉,避免不必要的影响,即只留一个以ifcfg开头的文件。

 

创建kube-proxy的service文件,vi  /usr/lib/systemd/system/kube-proxy.service

[Unit]

Description=Kubernetes Kube-proxy Server

Documentation=https://github.com/GoogleCloudPlatform/kubernetes

After=network.service

Requires=network.service

[Service]

EnvironmentFile=/etc/kubernetes/proxy

ExecStart=/usr/bin/kube-proxy $KUBE_PROXY_ARGS

Restart=on-failure

LimitNOFILE=65536

KillMode=process

[Install]

WantedBy=multi-user.target

 

创建配置文件,vi /etc/kubernetes/proxy

KUBE_PROXY_ARGS="--master=http://192.168.253.129:8080  --hostname-override=192.168.253.130  --logtostderr=true  --log-dir=/var/log/kubernetes  --v=2"

启动node1

systemctl  daemon-reload

systemctl  enable  kubelet

systemctl  start  kubelet

systemctl  enable  kube-proxy

systemctl  start  kube-proxy

将node1的虚拟机进行clone。

如果使用二进制安装kubernetes的方式失败,各种尝试不能成功,采用yum方式安装。

master安装etcd

yum install etcd –y

修改配置文件:vi  /etc/etcd/etcd.conf

ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379

ETCD_ADVERTISE_CLIENT_URLS="http://192.168.253.129:2379"

Systemctl  enable  etcd.service

systemctl  start  etcd.service

健康检查

etcdctl  -C  http://192.168.253.129:2379  cluster-health   

master安装kubernetes

yum install kubernetes-master.x86_64 –y

修改配置文件:vi  /etc/kubernetes/apiserver

KUBE_API_ADDRESS="--insecure-bind-address=0.0.0.0"

KUBE_API_PORT="--insecure-port=8080"

KUBE_ETCD_SERVERS="--etcd-servers=http://192.168.253.129:2379"

KUBE_ADMISSION_CONTROL="--admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ResourceQuota"

vi   /etc/kubernetes/config

KUBE_MASTER="--master=http://192.168.253.129:8080"

检查服务是否正常

kubectl  get  componentstatus

node节点安装kubernetes

yum  install  kubernetes-node.x86_64  –y

修改配置文件:vi  /etc/kubernetes/config

KUBE_MASTER="--master=http://192.168.253.129:8080"

vi  /etc/kubernetes/kubelet

KUBELET_ADDRESS="--address=0.0.0.0"

KUBELET_PORT="--port=10250"

KUBELET_HOSTNAME="--hostname-override=192.168.253.131"

KUBELET_API_SERVER="--api-servers=http://192.168.253.129:8080"

启动服务:

systemctl  enable  kubelet

systemctl  start  kubelet

systemctl  enable  kube-proxy

systemctl  start  kube-proxy

配置2个node,在master检查nodes状态,kubectl  get  nodes。

 

所有nodes正常后,在master创建nginx配置文件。

vi  /home/k8s/nginx-rc.yaml

apiVersion: v1

kind: ReplicationController

metadata:

 name: nginx

spec:

 replicas: 3

 selector:

  app: nginx

 template:

  metadata:

   labels:

    app: nginx

  spec:

   containers:

   - name: nginx

     image: nginx

     ports:

     - containerPort: 80

 

vi  /nginx-svc.yaml

apiVersion: v1

kind: Service

metadata:

 name: nginx

spec:

 type: NodePort

 ports:

  - port: 80

    nodePort: 30111

 selector:

   app: nginx

 

创建rc和svc,

kubectl  create  -f  nginx-rc.yaml

kubectl  create  -f  nginx-svc.yaml

检查服务是否正常,kubectl  get  svc,kubectl  get  pods。

get  pods,服务容器不能创建,原因是node节点不能拉取到镜像。解决办法,搭建私有仓库。

在node节点上,

docker  pull  registry

docker  run  -di  --name=registry  -p  5000:5000  registry

修改daemon.json,vi /etc/docker/daemon.json

{"insecure-registries":["192.168.253.134:5000"]}

重启docker服务。

systemctl  stop  docker

systemctl  daemon-reload

systemctl  start  docker

systemctl  status  docker

配置好私有仓库后。

docker  pull  kubernetes/pause

docker  tag  docker.io/kubernetes/pause:latest  192.168.253.134:5000/google_containers/pause-amd64.3.0

docker  push  192.168.253.134:5000/google_containers/pause-amd64.3.0

vi  /etc/kubernetes/kubelet

KUBELET_ARGS="--pod_infra_container_image=192.168.253.134:5000/google_containers/pause-amd64.3.0"

重启kubelet

systemctl  restart  kubelet

同样方式配置其他node。

配置完成后,在master查看pods,kubectl  get  pods。

浏览器访问192.168.253.129:30111不通,通过上述外网不能访问的方式不能解决,则需要在master和node上配置flanneld。

9,安装和配置flanneld

Master和node节点,安装etcd,安装flannel,yum  install  flannel  -y

修改配置文件vi  /etc/sysconfig/flanneld,修改etcd配置

FLANNEL_ETCD_ENDPOINTS=https://192.168.253.129:2379,https:// 192.168.253.130:2379,https:// 192.168.253.131:2379

etcdctl  mk  /atomic.io/network/config   '{ "Network": "172.17.0.0/16" }'

启动flanned前需要关闭docker。

Master节点按照etcd,flanneld,docker,kube-apiservice,kube-controller-manager,kube-scheduler顺序启动服务。

Node节点按照etcd,flanneld,docker,kubelet,kube-proxy。

通过ifconfig查看docker0的ip,ping其他节点的docker0的ip,查看是否能ping通。

10,常用命令

- 获取当前命名空间下的容器

  kubectl get pods

- 获取所有容器l列表

  kubectl get  all

- 创建 容器

  kubectl create -f kubernate-pvc.yaml

- 删除容器

  kubectl delete pods/test-pd  或者 kubectl delete -f rc-nginx.yaml

- 查看指定pod跑在哪个node上

  kubectl get pod /test-pd -o wide

- 查看容器日志

  Kubectl logs nginx-8586cf59-mwwtc

- 进入容器终端命令

  kubectl exec -it nginx-8586cf59-mwwtc /bin/bash

- 一个Pod里含有多个容器 用--container or -c 参数。

  例如:假如这里有个Pod名为my-pod,这个Pod有两个容器,分别名为main-app 和 helper-app,下面的命令将打开到main-app的shell的容器里。

  kubectl exec -it my-pod --container main-app -- /bin/bash

- 容器详情列表

  kubectl *describe* pod/mysql- m8rbl

- 查看容器状态

  kubectl get svc

三,核心技术

1,Pod

Pod是k8s的重要概念,每个pod都有一个特殊的被称为根容器的pause容器。Pause容器对应的镜像属于k8s平台的一部分,除了pause容器,每个pod还包含一个或多个紧密相关的用户业务容器。

每个pod都有应用的一个实例,有专用的ip。一个pod可以有多个容器,彼此间共享网络和存储资源,每个pod中有一个pause容器保存所有的容器状态。通过管理pause容器,达到管理pod中所有容器的效果。同一个pod的容器会被调度到相同node节点,不同节点间pod的通信基于虚拟二层网络技术实现。

Pod的yaml文件定义:

apiVersion: v1          #必选,版本号,例如v1

kind: Pod             #必选,Pod

metadata:             #必选,元数据

  name: string          #必选,Pod名称

  namespace: string       #必选,Pod所属的命名空间

  labels:             #自定义标签

    - name: string       #自定义标签名字

  annotations:          #自定义注释列表

    - name: string

spec:                #必选,Pod中容器的详细定义

  containers:           #必选,Pod中容器列表

  - name: string        #必选,容器名称

    image: string       #必选,容器的镜像名称

    imagePullPolicy: [Always | Never | IfNotPresent]  #获取镜像的策略 Alawys表示下载镜像 IfnotPresent表示优先使用本地镜像,否则下载镜像,Nerver表示仅使用本地镜像

    command: [string]       #容器的启动命令列表,如不指定,使用打包时使用的启动命令

    args: [string]         #容器的启动命令参数列表

    workingDir: string      #容器的工作目录

    volumeMounts:         #挂载到容器内部的存储卷配置

    - name: string         #引用pod定义的共享存储卷的名称,需用volumes[]部分定义的的卷名

      mountPath: string     #存储卷在容器内mount的绝对路径,应少于512字符

      readOnly: boolean     #是否为只读模式

    ports:              #需要暴露的端口库号列表

    - name: string         #端口号名称

      containerPort: int    #容器需要监听的端口号

      hostPort: int        #容器所在主机需要监听的端口号,默认与Container相同

      protocol: string      #端口协议,支持TCP和UDP,默认TCP

    env:              #容器运行前需设置的环境变量列表

    - name: string        #环境变量名称

      value: string       #环境变量的值

    resources:          #资源限制和请求的设置

      limits:           #资源限制的设置

        cpu: string       #Cpu的限制,单位为core数,将用于docker run --cpu-shares参数

        memory: string      #内存限制,单位可以为Mib/Gib,将用于docker run --memory参数

      requests:         #资源请求的设置

        cpu: string       #Cpu请求,容器启动的初始可用数量

        memory: string      #内存清楚,容器启动的初始可用数量

    livenessProbe:        #对Pod内个容器健康检查的设置,当探测无响应几次后将自动重启该容器,检查方法有exec、httpGet和tcpSocket,对一个容器只需设置其中一种方法即可

      exec:             #对Pod容器内检查方式设置为exec方式

        command: [string]   #exec方式需要制定的命令或脚本

      httpGet:            #对Pod内个容器健康检查方法设置为HttpGet,需要制定Path、port

        path: string

        port: number

        host: string

        scheme: string

        HttpHeaders:

        - name: string

          value: string

      tcpSocket:            #对Pod内个容器健康检查方式设置为tcpSocket方式

         port: number

       initialDelaySeconds: 0   #容器启动完成后首次探测的时间,单位为秒

       timeoutSeconds: 0      #对容器健康检查探测等待响应的超时时间,单位秒,默认1秒

       periodSeconds: 0       #对容器监控检查的定期探测时间设置,单位秒,默认10秒一次

       successThreshold: 0

       failureThreshold: 0

       securityContext:

         privileged: false

    restartPolicy: [Always | Never | OnFailure] #Pod的重启策略,Always表示一旦不管以何种方式终止运行,kubelet都将重启,OnFailure表示只有Pod以非0退出码退出才重启,Nerver表示不再重启该Pod

    nodeSelector: obeject     #设置NodeSelector表示将该Pod调度到包含这个label的node上,以key:value的格式指定

    imagePullSecrets:         #Pull镜像时使用的secret名称,以key:secretkey格式指定

    - name: string

    hostNetwork: false        #是否使用主机网络模式,默认为false,如果设置为true,表示使用宿主机网络

    volumes:              #在该pod上定义共享存储卷列表

    - name: string          #共享存储卷名称 (volumes类型有很多种)

      emptyDir: {}          #类型为emtyDir的存储卷,与Pod同生命周期的一个临时目录。为空值

      hostPath: string        #类型为hostPath的存储卷,表示挂载Pod所在宿主机的目录

        path: string        #Pod所在宿主机的目录,将被用于同期中mount的目录

      secret:             #类型为secret的存储卷,挂载集群与定义的secre对象到容器内部

        scretname: string 

        items:    

        - key: string

          path: string

      configMap:          #类型为configMap的存储卷,挂载预定义的configMap对象到容器内部

        name: string

        items:

        - key: string

          path: string   

 

k8s的容器运行在前台,而不是后台。应用需要改为前后台运行的方式。如果docker镜像的启动命令是后台执行程序,则k8s创建包含这个容器的pod之后运行完docker启动命令,就认为pod已经结束,将会立即销毁该pod。如果pod定义了rc,那么创建、销毁会陷入一个无限循环的过程中。

Pod可以由1个或多个容器组成。

1个容器的pod的yaml定义:

apiVersion: v1

kind: Pod

metadata:

  name: mytomcat

  labels:

    name: mytomcat

spec:

  containers:

  - name: mytomcat

    image: 192.168.126.112:5000/docker.io/tomcat

    ports:

- containerPort: 8080

 

两个紧耦合的容器组成的pod

apiVersion: v1

kind: Pod

metadata:

  name: myweb

  labels:

    name: tomcat-redis

spec:

  containers:

  - name: tomcat

    image: tomcat

    ports:

    - containerPort: 8080

  - name: redis

    image: redis

    ports:

    - containerPort: 6379

 

容器的创建kubectl  create  -f  xxx.yaml

查看容器kubectl  get  pod/po  <name>,kubectl  get  pod/po  <name>  -o  wide,kubectl   describe  pod/po  <name>。

删除pod,kubectl  delete  -f  pod  xxxx.yaml,kubectl  delete  pod  --all/<name>

Pod分为普通pod和静态pod。普通pod一旦被创建,就放入etcd中,然后被k8s调度到某个具体的node上并进行绑定,然后pod对应的node上的k8s进程实例化成为一组相关的docker容器并启动。默认情况下,当pod里某个容器停止时,k8s会自动检测到这个问题并且重新启动这个pod里某个容器,如果pod所在的node宕机,则会将这个node上的所有pod重新调度到其他节点上。静态pod是由k8s进行管理的仅存在特定node上的pod,它们不能通过api service进行管理,无法与replicationController、Deployment或DaemonSet进行关联,并且k8s也无法对它们进行健康检查。

Pod的状态:

Pending,api server已经创建了该pod,但是pod中一个或多个容器的镜像还没有创建,包括镜像下载过程。

Running,pod内所有容器已创建,且至少一个容器处于运行状态,正在启动或正在重启状态。

Completed,pod内所有容器都成功执行退出,且不会再重启。

Failed,pod内所有容器均退出,但至少一个容器退出失败。

Unkown,由于某种原因无法获取pod状态,例如网络通信不畅。

Pod重启策略,包括always,onFailure和never,默认值是always。

Always,当容器失效时,由k8s自动重启该容器。

OnFailure,当容器终止运行且退出码不为0时,由k8s自动重启该容器。

Never,不论容器运行状态如何,k8s都不会重启该容器。

每个pod都可以对其能使用的服务器上的计算资源设置限额,k8s中可以设置限额的计算资源有cpu与memory两种,其中cpu的资源单位为cpu数量,是一个绝对值而非相对值。Memory配额也是一个绝对值,它的单位是内存字节数。K8s里,一个计算资源进行配额限定需要设定两个参数,requests是该资源最小申请数量,系统必须满足要求;limits是该资源最大允许使用的量,不能突破,当容器识图使用超过限额的资源时,可能被k8s kill并重启。

sepc

 containers:

-  name: db

image: mysql

resources:

     requests:

      memory: “64mi”

      cpu: “250m”

     limits:

      memory: “128mi”

      cpu: “400m”

2,Label

Lable是k8s系统的核心之一。一个label是一个key=value的键值对,key和value可以自定义。Label可以附加到各种资源对象上,比如node、pod、service、rc等,一个资源对象可以定义任意数量的label,同一个label也可以被添加到任意数量的资源对象上,label通常在资源对象定义时确定,也可以在对象创建后动态添加或删除。Label最常见的用法是使用metadata.labels字段,来为对象添加label,通过spec.selector来引用对象。

apiVersion: extensions/v1beta1

kind: Deployment

metadata:

  name: frontend

spec:

  replicas: 1

  selector:

    matchLabels:

      tier: frontend

    matchExpressions:

      - {key: tier, operator: In, values: [frontend]}

  template:

    metadata:

      labels:

        app: app-demo

        tier: frontend

    spec:

      containers:

      - name: tomcat-demo

        image: tomcat

        ports:

        - containerPort: 8080

 

Label附加到k8s的各种资源上,是为了对资源对象进行分组管理,而分组管理的核心就是label  selector。Label与label  selector都是不能单独定义,必须附加在一些资源对象的定义文件上,一般附加在rc和service的资源定义文件中。

3,Replication  Controller

RC是k8s的核心之一,当定义一个rc并提交到k8s集群中后,master节点上的Controller  Manager组件就得到通知,定期检查系统中存活的pod,并确保目标pod实例的数量刚好等于rc的预期值,如果有过多或过少的pod运行,系统就会停掉或创建一些pod。此外,也可以通过修改rc的副本数量,实现pod的动态缩放功能。Kubectl  scale  rc  nginx  --replicas=5

由于rc与k8s代码中的模块replication  controller同名,所有在k8s1.2时,rc升级为replica  sets,官方解释为下一代rc。Rc与下一代rc的区别是,rpilca  sets支援基于集合的label  selector,而rc只支持基于等式的label  selector。Replica  set很少单独使用,主要被deployment等高层面的资源使用,形成一整套pod创建、删除、更新的机制。最好通过rc创建pod,不要直接创建pod,因为rc会通过rc管理pod副本,实现自动创建、补足、替换、删除pod副本,提高应用的容灾能力,减少由于节点崩溃等意外状况造成的损失。即使应用程序只有一个pod副本,也最好用rc来定义pod。

4,Replica  set

Replicaset跟replicationcontroller没有本质的不同,只是命名不同,以及replicaset支持集合式的selector。K8s官方强烈建议避免直接使用replicaset,而应该通过deployment来创建rs和pod。由于replicaset是replicationcontroller的代替物,因此用法基本相同,唯一的区别在于replicaset支持集合式的selector。

5,Deployment

Deployment是k8s1.2引入的新概念,引入的目标是为了更好的解决pod的编排问题,deployment内部使用replicaset来实现。Deployment的定义与replica set的定义很类似,除了以api声明与kind类型有所区别

apiVersion: extensions/v1beta1

kind: Deployment

metadata:

  name: frontend

spec:

  replicas: 1

  selector:

    matchLabels:

      tier: frontend

    matchExpressions:

      - {key: tier, operator: In, values: [frontend]}

  template:

    metadata:

      labels:

        app: app-demo

        tier: frontend

    spec:

      containers:

      - name: tomcat-demo

        image: tomcat

        ports:

        - containerPort: 8080

 

6,Horizontal  pod  autoscaler

Horizontal  pod  autoscal与rc、deployment一样,也属于一种k8s资源对象。通过追踪分析rc控制的所有目标pod的负载变化情况,来确定是否需要针对性地调整目标pod的副本数,这是hpa的实现原理。K8s对pod扩容与缩容提供了手动和自动两种模式。手动模式通过kubectl  scale命令对一个deployment/rc进行pod副本数量的设置。自动模式需要用户根据某个性能指标或者自定义业务目标,并制定pod副本数量的范围,系统将自动在这个范围内根据性能指标的变化进行调整。

Hpa控制器基本master和kube-controller-manager服务启动参数--horizontal-pod-autoscaler-sync-period定义的平均pod  cpu使用率。

apiVersion: apps/v1beta1

kind: Deployment

metadata:

  name: nginx-deployment

spec:

  replicas: 1

  template:

    metadata:

      name: nginx

      labels:

        app: nginx

    spec:

      containers:

      - name: nginx

        image: nginx

        resources:

          requests:

            cpu: 50m

        ports:

        - containerPort: 80

 

 

apiVersion: autoscaling/v1

kind: HorizontalPodAutoscaler

metadata:

  name: nginx-hpa

spec:

  scaleTargetRef:

    apiVersion: app/v1beta1

    kind: Deployment

    name: nginx-deployment

  minReplicas: 1

  maxReplicas: 10

  targetCPUUtilizationPercentage: 50

 

 

apiVersion: v1

kind: Service

metadata:

  name: nginx-svc

spec:

  ports:

  - port: 80

  selector:

    app: nginx

 

7,Volume

Volume是pod中能够被多个容器访问的共享木板路。K8s的volume定义在pod上,被一个pod中的多个容器挂在到具体的文件目录上。Volume和pod的生命周期相同,但与容器的生命周期不同,当容器终止或重启时,volume的数据也不会丢失。要使用volume,pod需要制定volume的类型和内容(spec.volumes字段)和映射到容器的位置(spec.containers.volumMounts字段)。K8s支持多种类型的valume,包括,emptyDir,hostPath,gcePersistentDisk,awsElasticBlockStore,nfs,iscsi,flocker,glusterfs等。

EmptyDir的volume创建于pod被调度到某个宿主机上的时候,而用一个pod内的容器都读写emptyDir中的同一个文件。一旦这个pod离开了这个宿主机,emptyDir中的数据就会永久删除。所以目前emptyDir类型的volume主要作临时空间,比如web服务器写日志或tmp文件需要的临时目录。

Hostpath属性的volume使得对应的容器能够访问当前宿主机上的指定目录。例如,需要运行一个访问docker系统目录的容器,那么就使用/var/lib/docker目录作为一个hostDir类型的volume;或者在一个容器内部运行cadvisor,就使用/dev/cgroups目录作为一个hostDir类型的volume。一旦这个pod离开了这个宿主机,hostDir中的数据虽然不会永久删除,但数据也不会随pod迁移到其他宿主机上。因此,需要注意的是,由于各个宿主机上的文件系统结构和内容并不一定完全相同,所以相同pod的hostDir可能会在不同的宿主机上表现的不一样。

Nfs类型的vulume,允许一块现有的网络硬盘在同一个pod内的容器间共享。

 

8,Namespace

Namespace主要用于实现多用户的资源隔离,通过将集群内部的资源对象分配到不同的namespace中,形成逻辑上的分组,便于不同的分组在共享使用整个集群的资源同时还能被分别管理。K8s集群在启动后,会创建一个名为default的namespace,如果不特别指明namespace,则用户创建的pod,rc,service都会被系统创建到整个默认的名为default的namespace中。

apiVersion: v1

kind: Namespace

metadata:

  name: development

 

查看namesapce的命令,kubectl  get   pod  --namespace=development。

9,Service

Service是k8s最核心的,通过创建service,可以为一组具有相同功能的容器应用提供一个统一的入口地址,并且将请求负载到后端的各个容器应用上。

Service的yaml定义:

apiVersion: v1

kind: Service

metadata:

  name: mywebapp-svc

spec:

  ports:

  - port: 8081

    targetPort: 8080

  selector:

app: mywebapp

 

对外提供服务的应用程序需要通过某种机制来实现,对于容器应用最简单的方式就是通过tcp/ip机制以及监听ip端口来实现。

通过kubectl  get  pods  -l  app=mywebapp  -o  yaml|grep  pod  ip来获取pod的ip地址和端口号来访问tomcat服务,但是直接通过pod的ip地址和端口访问应用服务是不可靠的,因为当pod所在node发生故障时,pod被k8s重新调度到另一台node,pod的地址会发生变化。通过配置文件定义service,通过kubectl  create创建,这样可以通过service地址来访问后端pod。

多端口service是指一个容器可能需要提供多个端口的服务,那么在service的定义中可以相应地设置为将多个端口对应到多个应用服务。

外部服务service,是应用系统需要将一个外部数据库作为后端服务进行连接,或将另一个集群namespace中的服务作为服务的后端,这时可以通过创建一个无label  selector的service来实现。

 

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐