kubernetes
一,概述1,简介2014年,谷歌发布了kubernetes开源项目,作用包括自动化容器应用程序的部署、扩展和管理。它通常和docker一起使用,并且整合多个运行着docker容器的主机集群。致力于让部署容器化的应用简单而高效。核心是能够自主管理容器来保证云平台的容器按照用户的期望运行。官网介绍,k8s的主要特性有:自动包装;横向缩放;自动保护署和回滚;存储编排;自我修复。目前,它是一个较新的基于容
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
如果push报Put http://192.168.253.128:5000/v1/repositories/google_containers/pause-amd64.3.0/: dial tcp 192.168.253.128:5000: connect: connection refused,首先查看docker的register容器是否启动(docker ps -a查看register的STATUS是否为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来实现。
更多推荐
所有评论(0)