第二章·Kubernetes安装配置指南
一.系统要求
Kubernetes系统由一组可执行程序组成,用户可以通过Kubernetes在GitHub的项目网站下载编译好的二进制文件或镜像文件,或者下载源码并自行将其编译为二进制文件。
安装Kubernetes对软件和硬件的系统要求如下表示
Kubernetes需要容器运行时(Container Runtime Interface,CRI)的支持,目前官方支持的容器运行时包括:Docker、Containerd、CRI-O和frakti等。本节以Docker作为容器运行环境,推荐的版本为Docker CE 19.03。
宿主机操作系统以CentOS 7为例,使用Systemd系统完成对Kubernetes服务的配置。其他Linux发行版的服务配置请参考相关的系统管理手册。为了便于管理,常见的做法是将Kubernetes服务程序配置为Linux系统开机自启动的服务。
需要注意的是,CentOS 7 默认启动了防火墙服务(firewalld.service),而Kubernetes的Master与工作Node之间会有大量的网络通信。安全的做法是在防火墙上配置各组件需要相互通信的端口号,具体要配置的端口号如下表所示。
其他组件可能还需要开通某些端口号,例如CNI网络插件calico需要179端口号;镜像库需要5000端口号等,需要根据系统要求逐个在防火墙服务上配置网络策略。
在安全的网络环境中,可以简单地关闭防火墙服务:
[root@k8s-m01 ~]# systemctl disable firewalld
[root@k8s-m01 ~]# systemctl stop firewalld
另外,建议在主机上禁用SELinux(修改文件/etc/sysconfig/selinux,将SELINUX=enforcing修改为SELINUX=disabled),让容器可以读取主机文件系统。随着Kubernetes对SELinux支持的增强,可以逐步启用SELinux机制,并通过Kubernetes设置容器的安全机制。
二.使用kubeadm工具快速安装Kubernetes集群
Kubernetes从1.4版本开始引入了命令行工具kubeadm,致力于简化集群的安装过程,到Kubernetes 1.13版本时,kubeadm工具达到GA阶段。本节讲解基于kubeadm的安装过程,操作系统以CentOS 7为例。
1.安装kubeadm
对kubeadm工具的安装在CentOS操作系统上可以通过yum工具一键完成。
首先配置yum源,官方yum源配置文件/etc/yum.repos.d/kubernetes.repo的内容如下:
[kubernetes]
name=Kubernetes Repository
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-\$basearch
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
exclude=kubelet kubeadm kubectl
然后运行yum install命令安装kubeadm、kubelet和kubectl:
[root@k8s-m01 ~]# yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
kubeadm将使用kubelet服务以容器方式部署和启动Kubernetes的主要服务,所以需要先启动kubelet服务。运行systemctl start命令启动kubelet服务,并设置为开机自启动:
[root@k8s-m01 ~]# systemctl start kubelet
[root@k8s-m01 ~]# systemctl enable kubelet
kubeadm还需要关闭Linux的swap系统交换区,这可以通过swapoff-a命令实现:
[root@k8s-m01 ~]# swapoff -a
2.修改kubeadm的默认配置
kubeadm的初始化控制平面(init)命令和加入节点(join)命令均可以通过指定的配置文件修改默认参数的值。kubeadm将配置文件以ConfigMap形式保存到集群中,便于后续的查询和升级工作。kubeadm config子命令提供了对这组功能的支持。
- kubeadm config print init-defaults:输出kubeadm init命令默认参数的内容。
- kubeadm config print join-defaults:输出kubeadm join命令默认参数的内容。
- kubeadm config migrate:在新旧版本之间进行配置转换。
- kubeadm config images list:列出所需的镜像列表。
- kubeadm config images pull:拉取镜像到本地。
例如,运行kubeadm config print init-defaults命令,可以获得默认的初始化参数文件:
[root@k8s-m01 ~]# kubeadm config print init-defaults > init.default.yaml
对生成的文件进行编辑,可以按需生成合适的配置。例如,若需要自定义镜像的仓库地址、需要安装的Kubernetes版本号及Pod的IP地址范围,则可以将默认配置修改如下:
apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
......
imageRepository: docker.io/dustise
kubernetesVersion: v1.19.0
networking:
podSubnet: "192.168.0.0/16"
......
将上面的内容保存为init-config.yaml备用。
3.下载Kubernetes的相关镜像
为了加快kubeadm创建集群的过程,可以预先将所需镜像下载完成。可以通过kubeadm config images list命令查看镜像列表,例如:
[root@k8s-m01 ~]# kubeadm config images list
k8s.gcr.io/kube-apiserver:v1.19.0
k8s.gcr.io/kube-controller-manager:v1.19.0
k8s.gcr.io/kube-scheduler:v1.19.0
k8s.gcr.io/kube-proxy:v1.19.0
k8s.gcr.io/pause:3.2
k8s.gcr.io/etcd:3.4.13-0
k8s.gcr.io/coredns/coredns:v1.7.0
如果无法访问k8s.gcr.io,则可以使用国内镜像托管站点进行下载,例如https://1nj0zren.mirror.aliyuncs.com,这可以通过修改Docker服务的配置文件(默认为/etc/docker/daemon.json)进行设置,例如:
{
"registry-mirrors": [
"https://1nj0zren.mirror.aliyuncs.com"
],
......
}
然后,使用kubeadm config images pull命令或者docker pull命令下载上述镜像,例如:
[root@k8s-m01 ~]# kubeadm config images pull --config=init-config.yaml
在镜像下载完成之后,就可以进行安装了。
4.运行kubeadm init命令安装master节点
至此,准备工作已经就绪,运行kubeadm init命令即可一键安装Kubernetes的Master节点,也称之为Kubernetes控制平面(Control Plane)。
在开始之前需要注意:kubeadm的安装过程不涉及网络插件(CNI)的初始化,因此kubeadm初步安装完成的集群不具备网络功能,任何Pod(包括自带的CoreDNS)都无法正常工作。而网络插件的安装往往对kubeadm init命令的参数有一定要求。例如,安装Calico插件时需要指定--pod-network-cidr=192.168.0.0/16。关于安装CNI网络插件的更多内容,可参考官方文档的说明。
kubeadm init命令在执行具体的安装操作之前,会执行一系列被称为pre-flight checks的系统预检查,以确保主机环境符合安装要求,如果检查失败就直接终止,不再进行init操作。用户可以通过kubeadm init phase preflight命令执行预检查操作,确保系统就绪后再执行init操作。如果不希望执行预检查,则也可以为kubeadm init命令添加--ignore-preflight-errors参数进行关闭。如表2.3所示是kubeadm检查的系统配置,对不符合要求的检查项以warning或error级别的信息给出提示。
另外,Kubernetes默认设置cgroup驱动(cgroupdriver)为“systemd”,而Docker服务的cgroup驱动默认值为“cgroupfs”,建议将其修改为“systemd”,与Kubernetes保持一致。这可以通过修改Docker服务的配置文件(默认为/etc/docker/daemon.json)进行设置:
{
"exec-opts": [
"native.cgroupdriver=systemd"
],
......
}
准备工作就绪之后,就可以运行kubeadm init命令,使用之前创建的配置文件一键安装Master节点(控制平面)了:
[root@k8s-m01 ~]# kubeadm init --config=init-config.yaml
看到“Your Kubernetes control-plane has initialized successfully!”的提示,就说明Master节点(控制平面)已经安装成功了。
接下来就可以通过kubectl命令行工具访问集群进行操作了。由于kubeadm默认使用CA证书,所以需要为kubectl配置证书才能访问Master。
按照安装成功的提示,非root用户可以将admin.conf配置文件复制到HOME目录的.kube子目录下,命令如下:
[root@k8s-m-01 ~]# mkdir -p $HOME/.kube
[root@k8s-m-01 ~]# sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
[root@k8s-m-01 ~]# sudo chown $(id -u):$(id -g) $HOME/.kube/config
如果用户是root,则也可以通过设置环境变量KUBECONFIG完成kubectl的配置:
[root@k8s-m-01 ~]# export KUBECONFIG=/etc/kubernetes/admin.conf
然后就可以使用kubectl命令行工具对Kubernetes集群进行访问和操作了。
例如查看命名空间kube-system中的ConfigMap列表:
[root@k8s-m01 ~]# kubectl -n kube-system get configmap
NAME DATA AGE
coredns 1 2d22h
extension-apiserver-authentication 6 2d22h
kube-proxy 2 2d22h
kubeadm-config 2 2d22h
kubelet-config-1.19 1 2d22h
到此,Kubernetes的Master节点已经可以工作了,但在集群内还是没有可用的Worker Node,并缺乏容器网络的配置。
接下来安装Worker Node,需要用到kubeadm init命令运行完成后的最后几行提示信息,其中包含将节点加入集群的命令(kubeadm join)和所需的Token。
5.将新的Node加入集群
对于新节点的添加,系统准备和安装Master节点的过程是一致的,在待安装的各个Node主机上进行下面的安装过程。
(1)安装kubeadm和kubelet(在Node上无须安装kubectl):
[root@k8s-m01 ~]# yum install kubelet kubeadm --disableexcludes=kubernetes
运行systemctl start命令启动kubelet服务,并设置为开机自启动:
[root@k8s-m01 ~]# systemctl start kubelet
[root@k8s-m01 ~]# systemctl enable kubelet
(2)使用kubeadm join命令加入集群,可以从安装Master节点的成功提示内容中复制完整的命令
[root@k8s-m01 ~]# kubeadm join 192.168.18.10:6443 --token s6svmh.lw88lchyl6m24tts --discovery-token-ca-cert-hash sha256:4d7e3e37e73176a97322e26fe501d2c27830a7bf3550df56f3a55b68395b507b
如果需要调整其他配置,则也可以通过自定义配置文件的方式进行操作,通过kubeadm config print join-defaults命令获取默认配置的内容,再进行修改,例如:
[root@k8s-m01 ~]# kubeadm config print join-default > join.confif.yaml
修改配置文件join.config.yaml的内容如下:
apiVersion: kubeadm.k8s.io/v1beta2
kind: JoinConfiguration
discovery:
bootstrapToken:
apiServerEndpoint: 192.168.18.10:6443
token: s6svmh.lw88lchyl6m24tts
unsafeSkipCAVerification: true
tlsBootstrapToken: s6svmh.lw88lchyl6m24tts
其中,apiServerEndpoint的值为Master服务的URL地址,token和tlsBootstrapToken的值来自使用kubeadm init安装Master时的最后一行提示信息。
运行kubeadm join命令,将本Node加入集群:
[root@k8s-m01 ~]# kubeadm join --config=join.config.yaml
成功将Node加入集群后,可以通过kubectl get nodes命令确认新的Node已加入:
[root@k8s-m01 ~]# kubectl get node
NAME STATUS ROLES AGE VERSION
k8s-m01 NotReady control-plane,master 2d23h v1.19.0
k8s-node01 NotReady <none> 2d23h v1.19.0
另外,在初始安装的Master节点上也启动了kubelet和kube-proxy,在默认情况下并不参与工作负载的调度。如果希望Master节点也作为Node角色,则可以运行下面的命令(删除Node的Label“node-role.kubernetes.io/master”),让Master节点也成为一个Node:
[root@k8s-m01 ~]# kubectl taint nodes --all node-role.kubernetes.io/master-node/k8s-m01 untained
[root@k8s-m01 ~]# kubectl get node
NAME STATUS ROLES AGE VERSION
k8s-m01 NotReady <none> 2d23h v1.19.0
k8s-node01 NotReady <none> 2d23h v1.19.0
6.安装网络插件
运行kubeadm init和join命令后,Kubernetes提示各节点均为NotReady状态,这是因为还没有安装CNI网络插件:
[root@k8s-m01 ~]# kubectl get node
NAME STATUS ROLES AGE VERSION
k8s-m01 NotReady <none> 2d23h v1.19.0
k8s-node01 NotReady <none> 2d23h v1.19.0
对于CNI网络插件,可以有许多选择。例如选择Calico CNI插件,运行下面的命令即可一键完成安装:
[root@k8s-m01 ~]# kubectl apply -y "https://docs.projectcalico.org/manifests/calico.yaml"
在CNI网络插件成功运行之后,再次查看Node,其状态会更新为Ready:
[root@k8s-m01 ~]# kubectl get node
NAME STATUS ROLES AGE VERSION
k8s-m01 Ready <none> 2d23h v1.19.0
k8s-node01 Ready <none> 2d23h v1.19.0
7.验证kubernetes集群是否工作正常
运行查看Pod的命令,验证Kubernetes集群服务的Pod是否创建成功且正常运行:
[root@k8s-m01 ~]# kubectl get pods --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
default mysql-596b96985c-llgt7 1/1 Running 0 2d23h
default tomcat-demo-5f7586764d-rbrqr 1/1 Running 4 2d23h
kube-system calico-kube-controllers-796cc7f49d-wjqr8 1/1 Running 0 2d23h
kube-system calico-node-s7vnr 1/1 Running 0 2d23h
kube-system calico-node-vvxr9 1/1 Running 4 2d23h
kube-system calico-node-xrmlk 1/1 Running 0 2d23h
kube-system coredns-59d64cd4d4-6jmr2 1/1 Running 0 2d23h
kube-system coredns-59d64cd4d4-pqnkm 1/1 Running 0 2d23h
kube-system etcd-k8s-m01 1/1 Running 0 2d23h
kube-system kube-apiserver-k8s-m01 1/1 Running 0 2d23h
kube-system kube-controller-manager-k8s-m01 1/1 Running 0 2d23h
kube-system kube-proxy-59gdq 1/1 Running 0 2d23h
kube-system kube-proxy-lj4rw 1/1 Running 4 2d23h
kube-system kube-proxy-npkr9 1/1 Running 0 2d23h
kube-system kube-scheduler-k8s-m01 1/1 Running 0 2d23h
如果发现有状态错误的Pod,则可以运行kubectl--namespace=kube-system describe pod
至此,通过kubeadm工具就实现了Kubernetes集群的快速搭建。
如果安装失败,则可以运行kubeadm reset命令将主机恢复原状,重新运行kubeadm init命令再次进行安装。
三.以二进制文件方式安装Kubernetes安全高可用集群
通过kubeadm能够快速部署一个Kubernetes集群,但是如果需要精细调整Kubernetes各组件服务的参数及安全设置、高可用模式等,管理员就可以使用Kubernetes二进制文件进行部署。
本节基于Kubernetes 1.19版本,以二进制文件方式对如何配置、部署一个启用了安全机制、3节点高可用的Kubernetes集群进行说明。对于测试环境,可以适当进行简化,将某些组件部署为单点。
1.Master高可用部署架构
在Kubernetes系统中,Master节点扮演着总控中心的角色,通过不间断地与各个工作节点(Node)通信来维护整个集群的健康工作状态,集群中各资源对象的状态则被保存在etcd数据库中。如果Master不能正常工作,各Node就会处于不可管理状态,用户就无法管理在各Node上运行的Pod,其重要性不言而喻。同时,如果Master以不安全方式提供服务(例如通过HTTP的8080端口号),则任何能够访问Master的客户端都可以通过API操作集群中的数据,可能导致对数据的非法访问或篡改。
在正式环境中应确保Master的高可用,并启用安全访问机制,至少包括以下几方面。
- Master的kube-apiserver、kube-controller-mansger和kube-scheduler服务至少以3个节点的多实例方式部署。
- Master启用基于CA认证的HTTPS安全机制。
- etcd至少以3个节点的集群模式部署。
- etcd集群启用基于CA认证的HTTPS安全机制。
- Master启用RBAC授权模式
Master的高可用部署架构如图2.1所示。
在Master的3个节点之前,应通过一个负载均衡器提供对客户端的唯一访问入口地址,负载均衡器可以选择硬件或者软件进行搭建。软件负载均衡器可以选择的方案较多,本文以HAProxy搭配Keepalived为例进行说明。主流硬件负载均衡器有F5、A10等,需要额外采购,其负载均衡配置规则与软件负载均衡器的配置类似,本文不再赘述。
本例中3台主机的IP地址分别为192.168.18.3、192.168.18.4、192.168.18.5,负载均衡器使用的VIP为192.168.18.100。
下面分别对etcd、负载均衡器、Master、Node等组件如何进行高可用部署、关键配置、CA证书配置等进行详细说明。
2.创建CA证书
为etcd和Kubernetes服务启用基于CA认证的安全机制,需要CA证书进行配置。如果组织能够提供统一的CA认证中心,则直接使用组织颁发的CA证书即可。如果没有统一的CA认证中心,则可以通过颁发自签名的CA证书来完成安全配置。
etcd和Kubernetes在制作CA证书时,均需要基于CA根证书,本文以为Kubernetes和etcd使用同一套CA根证书为例,对CA证书的制作进行说明。
CA证书的制作可以使用openssl、easyrsa、cfssl等工具完成,本文以openssl为例进行说明。下面是创建CA根证书的命令,包括私钥文件ca.key和证书文件ca.crt:
[root@k8s-m01 ~]# openssl genrsa -out ca.key 2048
[root@k8s-m01 ~]# openssl req -x509 -new -nodes -key ca.key -subj "/CN=192.168.18.3" -days 36500 -out ca.crt
主要参数如下。
◎ -subj:“/CN”的值为Master主机名或IP地址。
◎ -days:设置证书的有效期。
将生成的ca.key和ca.crt文件保存在/etc/kubernetes/pki目录下。
3.部署安全的etcd高可用集群
etcd作为Kubernetes集群的主数据库,在安装Kubernetes各服务之前需要首先安装和启动。
1.下载etcd二进制文件,配置systemd服务
从GitHub官网下载etcd二进制文件,例如etcd-v3.4.13-linux-amd64.tar.gz,如图2.2所示。
解压缩后得到etcd和etcdctl文件,将它们复制到/usr/bin目录下。
然后将其部署为一个systemd的服务,创建systemd服务配置文件/usr/lib/systemd/system/etcd.service,内容示例如下:
[Unit]
Description=etcd key-value store
Documentation=https://github.com/etcd.io/etcd
After=network.target
[Service]
EnvironmentFile=/etc/etcd/etcd.conf
ExecStart=/usr/bin/etcd
Restart=always
[Install]
WantedBy=multi-user.target
其中,EnvironmentFile指定配置文件的全路径,例如/etc/etcd/etcd.conf,其中的参数以环境变量的格式进行配置。
接下来先对etcd需要的CA证书配置进行说明。对于配置文件/etc/etcd/etcd.conf中的完整配置参数,将在创建完CA证书后统一说明。
2.创建etcd的CA证书
先创建一个x509 v3配置文件etcd_ssl.cnf,其中subjectAltName参数(alt_names)包括所有etcd主机的IP地址,例如:
[ req ]
req_extensions = v3_req
distinguished_name = req_distinguished_name
[ req_distinguished_name ]
[ v3_req ]
basicConstraints = CA:FALSE
KeyUsage = nonRepudiation, disitalSignature, keyEncipherment
subjectAltName = @alt_names
[ alt_names ]
IP.1 = 192.168.18.3
IP.2 = 192.168.18.4
IP.3 = 192.168.18.5
然后使用openssl命令创建etcd的服务端CA证书,包括etcd_server.key和etcd_server.crt文件,将其保存到/etc/etcd/pki目录下:
[root@k8s-m01 ~]# openssl genrsa -out etcd_server.key 2048
[root@k8s-m01 ~]# openssl req -new -key etcd_server.key -config etcd_ssl.cnf -subj "/CN=etcd-server" -out etcd_server.csr
[root@k8s-m01 ~]# openssl x509 -req -in etcd_server.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -days 36500 -extensions v3_req -extfile etcd_ssl.cnf -out etcd_server.crt
再创建客户端使用的CA证书,包括etcd_client.key和etcd_client.crt文件,也将其保存到/etc/etcd/pki目录下,后续供kube-apiserver连接etcd时使用:
[root@k8s-m01 ~]# openssl genrsa -out etcd_client.key 2048
[root@k8s-m01 ~]# openssl req -new -key etcd_server.key -config etcd_ssl.cnf -subj "/CN=etcd-client" -out etcd_server.csr
[root@k8s-m01 ~]# openssl x509 -req -in etcd_client.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -days 36500 -extensions v3_req -extfile etcd_ssl.cnf -out etcd_client.crt
3.etcd参数配置说明
接下来对3个etcd节点进行配置。etcd节点的配置方式包括启动参数、环境变量、配置文件等,本例使用环境变量方式将其配置到/etc/etcd/etcd.conf文件中,供systemd服务读取。
3个etcd节点将被部署在192.168.18.3、192.168.18.4和192.168.18.5 3台主机上,配置文件/etc/etcd/etcd.conf的内容示例如下:
# 节点1的配置
ETCD_NAME=etcd1
ETCD_DATA_DIR=/etc/etcd/data
ETCD_CERT_FILE=/etc/etcd/pki/etcd_server.crt
ETCD_KEY_FILE=/etc/etcd/pki/etcd_server.key
ETCD_TRUSTED_CA_FILE=/etc/kubernetes/pki/ca.crt
ETCD_CLIENT_CERT_AUTH=true
ETCD_LISTEN_CLIENT_URLS=https://192.168.18.3:2379
ETCD_ADVERTISE_CLIENT_URLS=https://192.168.18.3:2379
ETCD_PEER_CERT_FILE=/etc/etcd/pki/etcd_server.crt
ETCD_PEER_KEY_FILE=/etc/etcd/pki/etcd_server.key
ETCD_PEER_TRUSTED_CA_FILE=/etc/kubernetes/pki/ca.crt
ETCD_LISTEN_PEER_URLS=https://192.168.18.3:2380
ETCD_INITIAL_ADVERTISE_PEER_URLS=https://192.168.18.3:2380
ETCD_INITIAL_CLUSTER_TOKEN=etcd_cluster
ETCD_INITIAL_CLUSTER="etcd1=https://192.168.18.3:2380,etcd2=https://192.168.18.4:2380,etcd3=https://192.168.18.5:2380"
ETCD_INITIAL_CLUSTER_STATE=NEW
# 节点2的配置
ETCD_NAME=etcd2
ETCD_DATA_DIR=/etc/etcd/data
ETCD_CERT_FILE=/etc/etcd/pki/etcd_server.crt
ETCD_KEY_FILE=/etc/etcd/pki/etcd_server.key
ETCD_TRUSTED_CA_FILE=/etc/kubernetes/pki/ca.crt
ETCD_CLIENT_CERT_AUTH=true
ETCD_LISTEN_CLIENT_URLS=https://192.168.18.4:2379
ETCD_ADVERTISE_CLIENT_URLS=https://192.168.18.4:2379
ETCD_PEER_CERT_FILE=/etc/etcd/pki/etcd_server.crt
ETCD_PEER_KEY_FILE=/etc/etcd/pki/etcd_server.key
ETCD_PEER_TRUSTED_CA_FILE=/etc/kubernetes/pki/ca.crt
ETCD_LISTEN_PEER_URLS=https://192.168.18.4:2380
ETCD_INITIAL_ADVERTISE_PEER_URLS=https://192.168.18.4:2380
ETCD_INITIAL_CLUSTER_TOKEN=etcd_cluster
ETCD_INITIAL_CLUSTER="etcd1=https://192.168.18.3:2380,etcd2=https://192.168.18.4:2380,etcd3=https://192.168.18.5:2380"
ETCD_INITIAL_CLUSTER_STATE=NEW
# 节点3的配置
ETCD_NAME=etcd3
ETCD_DATA_DIR=/etc/etcd/data
ETCD_CERT_FILE=/etc/etcd/pki/etcd_server.crt
ETCD_KEY_FILE=/etc/etcd/pki/etcd_server.key
ETCD_TRUSTED_CA_FILE=/etc/kubernetes/pki/ca.crt
ETCD_CLIENT_CERT_AUTH=true
ETCD_LISTEN_CLIENT_URLS=https://192.168.18.5:2379
ETCD_ADVERTISE_CLIENT_URLS=https://192.168.18.5:2379
ETCD_PEER_CERT_FILE=/etc/etcd/pki/etcd_server.crt
ETCD_PEER_KEY_FILE=/etc/etcd/pki/etcd_server.key
ETCD_PEER_TRUSTED_CA_FILE=/etc/kubernetes/pki/ca.crt
ETCD_LISTEN_PEER_URLS=https://192.168.18.5:2380
ETCD_INITIAL_ADVERTISE_PEER_URLS=https://192.168.18.5:2380
ETCD_INITIAL_CLUSTER_TOKEN=etcd_cluster
ETCD_INITIAL_CLUSTER="etcd1=https://192.168.18.3:2380,etcd2=https://192.168.18.4:2380,etcd3=https://192.168.18.5:2380"
ETCD_INITIAL_CLUSTER_STATE=NEW
主要配置参数包括为客户端和集群其他节点配置的各监听URL地址(均为HTTPS URL地址),并配置相应的CA证书参数。
etcd服务相关的参数如下。
- ETCD_NAME:etcd节点名称,每个节点都应不同,例如etcd1、etcd2、etcd3。
- ETCD_DATA_DIR:etcd数据存储目录,例如/etc/etcd/data/etcd1。
- ETCD_LISTEN_CLIENT_URLS和ETCD_ADVERTISE_CLIENT_URLS:为客户端提供的服务监听URL地址,例如https://192.168.18.3:2379。
- ETCD_LISTEN_PEER_URLS和ETCD_INITIAL_ADVERTISE_PEER_URLS:为本集群其他节点提供的服务监听URL地址,例如https://192.168.18.3:2380。
- ETCD_INITIAL_CLUSTER_TOKEN:集群名称,例如etcd-cluster。
- ETCD_INITIAL_CLUSTER:集群各节点的endpoint列表,例如"etcd1=https://192.168.18.3:2380,etcd2=https://192.168.18.4:2380,etcd3=https://192.168.18.5:2380"。
- ETCD_INITIAL_CLUSTER_STATE:初始集群状态,新建集群时设置为“new”,集群已存在时设置为“existing”。
CA证书相关的配置参数如下。
- ETCD_CERT_FILE:etcd服务端CA证书-crt文件全路径,例如/etc/etcd/pki/etcd_server.crt。
- ETCD_KEY_FILE:etcd服务端CA证书-key文件全路径,例如/etc/etcd/pki/etcd_server.key。
- ETCD_TRUSTED_CA_FILE:CA根证书文件全路径,例如/etc/kubernetes/pki/ca.crt。
- ETCD_CLIENT_CERT_AUTH:是否启用客户端证书认证。
- ETCD_PEER_CERT_FILE:集群各节点相互认证使用的CA证书-crt文件全路径,例如/etc/etcd/pki/etcd_server.crt。
- ETCD_PEER_KEY_FILE:集群各节点相互认证使用的CA证书-key文件全路径,例如/etc/etcd/pki/etcd_server.key。
- ETCD_PEER_TRUSTED_CA_FILE:CA根证书文件全路径,例如/etc/kubernetes/pki/ca.crt。
4.启动etcd集群
基于systemd的配置,在3台主机上分别启动etcd服务,并设置为开机自启动:
[root@k8s-m01 ~]# systemctl restart etcd && systemctl enable etcd
然后用etcdctl客户端命令行工具携带客户端CA证书,运行etcdctl endpoint health命令访问etcd集群,验证集群状态是否正常,命令如下:
[root@k8s-m01 ~]# etcdctl --cacert=/etc/kubernetes/pki/ca.crt --cert=/etc/etcd/pki/etcd_client.crt --key=/etc/etcd/pki/etcd_client.key --endpoints=https://192.168.18.3:2379,https://192.168.18.4:2379,https://192.168.18.5:2379 endpoint health
结果显示各节点状态均为“healthy”,说明集群正常运行。
至此,一个启用了HTTPS的3节点etcd集群就部署完成了,更多的配置参数请参考etcd官方文档的说明。
4.部署安全的Kubernetes Master高可用集群
1. 下载Kubernetes服务的二进制文件
首先,从Kubernetes的官方GitHub代码库页面下载各组件的二进制文件,在Releases页面找到需要下载的版本号,单击CHANGELOG链接,跳转到已编译好的Server端二进制(Server Binaries)文件的下载页面进行下载。
在压缩包kubernetes.tar.gz内包含了Kubernetes的全部服务二进制文件和容器镜像文件,也可以分别下载Server Binaries和Node Binaries二进制文件。在Server Binaries中包含不同系统架构的服务端可执行文件,例如kubernetes-server-linux-amd64.tar.gz文件包含了x86架构下Kubernetes需要运行的全部服务程序文件;Node Binaries则包含了不同系统架构、不同操作系统的Node需要运行的服务程序文件,包括Linux版和Windows版等。
主要的服务程序二进制文件列表如下表所示。
在Kubernetes的Master节点上需要部署的服务包括etcd、kube-apiserver、kube-controller-manager和kube-scheduler。
在工作节点(Worker Node)上需要部署的服务包括docker、kubelet和kube-proxy。
将Kubernetes的二进制可执行文件复制到/usr/bin目录下,然后在/usr/lib/systemd/system目录下为各服务创建systemd服务配置文件(完整的systemd系统知识请参考Linux的相关手册),这样就完成了软件的安装。
下面对每个服务的配置进行详细说明。
2.部署kube-apiserver服务
(1)设置kube-apiserver服务需要的CA相关证书。准备master_ssl.cnf文件用于生成x509 v3版本的证书,示例如下:
[ req ]
req_extensions = v3_req
distinguished_name = req_distinguished_name
[ req_distinguished_name ]
[ v3_req ]
basicConstraints = CA:FALSE
KeyUsage = nonRepudiation, disitalSignature, keyEncipherment
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = kubernetes
DNS.2 = kubernetes.default
DNS.3 = kubernetes.default.svc
DNS.4 = kubernetes.default.svc.cluster.local
DNS.5 = k8s-1
DNS.6 = k8s-2
DNS.7 = k8s-3
IP.1 = 169.169.0.1
IP.2 = 192.168.18.3
IP.3 = 192.168.18.4
IP.4 = 192.168.18.5
IP.5 = 192.168.18.100
在该文件中主要需要在subjectAltName字段([alt_names])设置Master服务的全部域名和IP地址,包括:
- DNS主机名,例如k8s-1、k8s-2、k8s-3等;
- Master Service虚拟服务名称,例如kubernetes.default等;
- IP地址,包括各kube-apiserver所在主机的IP地址和负载均衡器的IP地址,例如192.168.18.3、192.168.18.4、192.168.18.5和192.168.18.100;
- Master Service虚拟服务的ClusterIP地址,例如169.169.0.1。
然后使用openssl命令创建kube-apiserver的服务端CA证书,包括apiserver.key和apiserver.crt文件,将其保存到/etc/kubernetes/pki目录下:
[root@k8s-m01 ~]# openssl genrsa -out apiserver.key 2048
[root@k8s-m01 ~]# openssl req -new -key apiserver.key -config master_ssl.cnf -subj "/CN=192.168.18.3" -out apiserver.csr
[root@k8s-m01 ~]# openssl x509 -req -in apiserver.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 36500 -extensions v3_req -extfile master_ssl.cnf -out apiserver.crt
(2)为kube-apiserver服务创建systemd服务配置文件/usr/lib/systemd/system/kube-apiserver.service,内容如下:
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/kubernetes/kubernetes
[Service]
EnvironmentFile=/etc/kubernetes/apiserver
ExecStart=/usr/bin/kube-apiserver $KUBE_API_ARGS
Restart=always
[Install]
WantedBy=multi-user.target
(3)配置文件/etc/kubernetes/apiserver的内容通过环境变量KUBE_API_ARGS设置kube-apiserver的全部启动参数,包含CA安全配置的启动参数示例如下:
KUBE_API_ARGS="--insecure-port=0 \
--secure-port=6443 \
--tls-cert-file=/etc/kubernetes/pki/apiserver.crt \
--tls-private-key-file=/etc/kubernetes/pki/apiserver.key \
--client-ca-file=/etc/kubernetes/pki/ca.crt \
--apiserver-count=3 --endpoint-reconciler-type=master-count \
--etcd-servers=https://192.168.18.3:2379,https://192.168.18.4:2379,https://192.168.18.5:2379 \
--etcd-cafile=/etc/kubernetes/pki/ca.crt \
--etcd-certfile=/etc/etcd/pki/etcd_client.crt \
--etcd-keyfile=/etc/etcd/pki/etcd_client.key \
--service-cluster-ip-range=169.169.0.0/16 \
--service-node-port-range=30000-32767 \
--allow-privileged=true \
--logtostderr=false --log-dir=/var/log/kubernetes --v=0"
对主要参数说明如下。
- --secure-port:HTTPS端口号,默认值为6443。
- --insecure-port:HTTP端口号,默认值为8080,设置为0表示关闭HTTP访问。
- --tls-cert-file:服务端CA证书文件全路径,例如/etc/kubernetes/pki/apiserver.crt。
- --tls-private-key-file:服务端CA私钥文件全路径,例如/etc/kubernetes/pki/apiserver.key。
- --client-ca-file:CA根证书全路径,例如/etc/kubernetes/pki/ca.crt。
- --apiserver-count:API Server实例数量,例如3,需要同时设置参数--endpoint-reconciler-type=master-count。
- --etcd-servers:连接etcd的URL列表,这里使用HTTPS,例如https://192.168.18.3:2379、https://192.168.18.4:2379和https://192.168.18.5:2379。
- --etcd-cafile:etcd使用的CA根证书文件全路径,例如/etc/kubernetes/pki/ca.crt。
- --etcd-certfile:etcd客户端CA证书文件全路径,例如/etc/etcd/pki/etcd_client.crt。
- --etcd-keyfile:etcd客户端私钥文件全路径,例如/etc/etcd/pki/etcd_client.key。
- --service-cluster-ip-range:Service虚拟IP地址范围,以CIDR格式表示,例如169.169.0.0/16,该IP范围不能与物理机的IP地址有重合。
- --service-node-port-range:Service可使用的物理机端口号范围,默认值为30000~32767。
- --allow-privileged:是否允许容器以特权模式运行,默认值为true。
- --logtostderr:是否将日志输出到stderr,默认值为true,当使用systemd系统时,日志将被输出到journald子系统。设置为false表示不输出到stderr,可以输出到日志文件。
- --log-dir:日志的输出目录,例如/var/log/kubernetes。
- --v:日志级别。
(4)在配置文件准备完毕后,在3台主机上分别启动kube-apiserver服务,并设置为开机自启动:
[root@k8s-m01 ~]# systemctl start kube-apiserver && systemctl enable kube-apiserver
3.创建客户端CA证书
kube-controller-manager、kube-scheduler、kubelet和kube-proxy服务作为客户端连接kube-apiserver服务,需要为它们创建客户端CA证书进行访问。这里以对这几个服务统一创建一个证书作为示例。
(1)通过openssl工具创建CA证书和私钥文件,命令如下
[root@k8s-m01 ~]# openssl genrsa -out client.key 2048
[root@k8s-m01 ~]# openssl req -new -key client.key -subj "/CN=admin" -out client.csr
[root@k8s-m01 ~]# openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 36500
其中,-subj参数中“/CN”的名称可以被设置为“admin”,用于标识连接kube-apiserver的客户端用户的名称。
(2)将生成的client.key和client.crt文件保存在/etc/kubernetes/pki目录下。
4.创建客户端连接kube-apiserver服务所需的kubeconfig配置文件
本节为kube-controller-manager、kube-scheduler、kubelet和kube-proxy服务统一创建一个kubeconfig文件作为连接kube-apiserver服务的配置文件,后续也作为kubectl命令行工具连接kube-apiserver服务的配置文件。
在Kubeconfig文件中主要设置访问kube-apiserver的URL地址及所需CA证书等的相关参数,示例如下:
apiVersion: v1
kind: Config
clusters:
- name: default
cluster:
server: https://192.168.18.100:9443
certificate-authority: /etc/kubernetes/pki/ca.crt
users:
- name: admin
user:
client-certificate: /etc/kubernetes/pki/client.crt
client-key: /etc/kubernetes/pki/client.key
contexts:
- context:
cluster: default
user: admin
name: default
current-context: default
其中的关键配置参数如下。
- server URL地址:配置为负载均衡器(HAProxy)使用的VIP地址(如192.168.18.100)和HAProxy监听的端口号(如9443)。
- client-certificate:配置为客户端证书文件(client.crt)全路径。
- client-key:配置为客户端私钥文件(client.key)全路径。
- certificate-authority:配置为CA根证书(ca.crt)全路径。
- users中的user name和context中的user:连接API Server的用户名,设置为与客户端证书中的“/CN”名称保持一致,例如“admin”。
将kubeconfig文件保存到/etc/kubernetes目录下。
5.部署kube-controller-manager服务
(1)为kube-controller-manager服务创建systemd服务配置文件/usr/lib/systemd/system/kube-controller-manager.service,内容如下:
[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/kubernetes/kubernetes
[Service]
EnvironmentFile=/etc/kubernetes/controller-manager
ExecStart=/usr/bin/kube-controller-manager $KUBE_CONTROLLER_MANAGER_ARGS
Restart=always
[Install]
WantedBy=multi-user.target
(2)配置文件/etc/kubernetes/controller-manager的内容为通过环境变量KUBE_CONTROLLER_MANAGER_ARGS设置的kube-controller-manager的全部启动参数,包含CA安全配置的启动参数示例如下:
KUBE_CONTROLLER_MANAGER_ARGS="--kubeconfig=/etc/kubernetes/kubeconfig \
--leader-elect=true \
--service-cluster-ip-range=169.169.0.0/16 \
--service-account-private-key-file=/etc/kubernetes/pki/apiserver.key \
--root-ca-file=/etc/kubernetes/pki/ca.crt \
--log-dir=/var/log/kubernetes --logtostderr=false --v=0"
对主要参数说明如下。
- --kubeconfig:与API Server连接的相关配置。
- --leader-elect:启用选举机制,在3个节点的环境中应被设置为true。
- --service-account-private-key-file:为ServiceAccount自动颁发token使用的私钥文件全路径,例如/etc/kubernetes/pki/apiserver.key。
- --root-ca-file:CA根证书全路径,例如/etc/kubernetes/pki/ca.crt。
- --service-cluster-ip-range:Service虚拟IP地址范围,以CIDR格式表示,例如169.169.0.0/16,与kube-apiserver服务中的配置保持一致。
(3)配置文件准备完毕后,在3台主机上分别启动kube-controller-manager服务,并设置为开机自启动:
[root@k8s-m01 ~]# systemctl start kube-controller-manager && systemctl enable kube-controller-manager
6.部署kube-scheduler服务
(1)为kube-scheduler服务创建systemd服务配置文件/usr/lib/systemd/system/kube-scheduler.service,内容如下:
[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/kubernetes/kubernetes
[Service]
EnvironmentFile=/etc/kubernetes/scheduler
ExecStart=/usr/bin/kube-scheduler $KUBE_SCHEDULER_ARGS
Restart=always
[Install]
WantedBy=multi-user.target
(2)配置文件/etc/kubernetes/scheduler的内容为通过环境变量KUBE_SCHEDULER_ARGS设置的kube-scheduler的全部启动参数,示例如下:
KUBE_SCHEDULER_ARGS="--kubeconfig=/etc/kubernetes/kubeconfig \
--leader-elect=true \
--logtostderr=false --log-dir=/var/log/kubernetes --v=0"
对主要参数说明如下。
- --kubeconfig:与API Server连接的相关配置。
- --leader-elect:启用选举机制,在3个节点的环境中应被设置为true。
(3)在配置文件准备完毕后,在3台主机上分别启动kube-scheduler服务,并设置为开机自启动:
[root@k8s-m01 ~]# systemctl start kube-scheduler && systemctl enable kube-scheduler
通过systemctl status
[root@k8s-m01 ~]# systemctl status kube-apiserver
7.使用HAProxy和keepalived部署高可用负载均衡器
接下来,在3个kube-apiserver服务的前端部署HAProxy和keepalived,使用VIP 192.168.18.100作为Master的唯一入口地址,供客户端访问。
将HAProxy和keepalived均部署为至少有两个实例的高可用架构,以避免单点故障。下面以在192.168.18.3和192.168.18.4两台服务器上部署为例进行说明。HAProxy负责将客户端请求转发到后端的3个kube-apiserver实例上,keepalived负责维护VIP 192.168.18.100的高可用。HAProxy和keepalived的部署架构如图2.5所示。
接下来对部署HAProxy和keepalived组件进行说明。
1)部署两个HAProxy实例
准备HAProxy的配置文件haproxy.cfg,内容示例如下:
global
log 127.0.0.1 local2
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4096
user haproxy
group haproxy
daemon
stats socket /var/lib/haproxy/stats
defaults
mode http
log global
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.0/8
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000
frontend kube-apiserver
mode tcp
bind *.9443
option tcplog
default_backend kube-apiserver
listen stats
mode http
bind *.8888
stats auth admin:password
stats refresh 5s
stats realm HAProxy\ Statistics
stats uri /stats
log 127.0.0.1 local3 err
backend kube-apiserver
mode tcp
balance roundrobin
server k8s-master1 192.168.18.3:6443 check
server k8s-master1 192.168.18.4:6443 check
server k8s-master1 192.168.18.5:6443 check
对主要参数说明如下。
- frontend:HAProxy的监听协议和端口号,使用TCP,端口号为9443。
- backend:后端3个kube-apiserver的地址,以IP:Port方式表示,例如192.168.18.3:6443、192.168.18.4:6443和192.168.18.5:6443;mode字段用于设置协议,此处为tcp;balance字段用于设置负载均衡策略,例如roundrobin为轮询模式。
- listen stats:状态监控的服务配置,其中,bind用于设置监听端口号为8888;stats auth用于配置访问账号;stats uri用于配置访问URL路径,例如/stats。
下面以Docker容器方式运行HAProxy且镜像使用haproxytech/haproxy-debian为例进行说明。
在两台服务器192.168.18.3和192.168.18.4上启动HAProxy,将配置文件haproxy.cfg挂载到容器的/usr/local/etc/haproxy目录下,启动命令如下:
[root@k8s-m01 ~]# docker run -d --name k8s-haproxy \
-- nethost \
--restart=always \
-v ${PWD}/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro \
haproxytech/haproxy-debian:2.3
在一切正常的情况下,通过浏览器访问http://192.168.18.3:8888/stats地址即可访问HAProxy的管理页面,登录后查看到的主页界面如图2.6所示。
这里主要关注最后一个表格,其内容为haproxy.cfg配置文件中backend配置的3个kube-apiserver地址,它们的状态均为“UP”,表示与3个kube-apiserver服务成功建立连接,说明HAProxy工作正常。
2)部署两个keepalived实例
Keepalived用于维护VIP地址的高可用,同样在192.168.18.3和192.168.18.4两台服务器上进行部署。主要需要配置keepalived监控HAProxy的运行状态,当某个HAProxy实例不可用时,自动将VIP地址切换到另一台主机上。下面对keepalived的配置和启动进行说明。
在第1台服务器192.168.18.3上创建配置文件keepalived.conf,内容如下:
! Configuration File for keepalived
global_defs {
router_id LVS_1
}
vrrp_script checkhaproxy
{
script "/usr/bin/check-haproxy.sh"
interval 2
weight -30
}
vrrp_instance VI_1 {
state MASTER
interface ens33
virtual_router_id 51
priority 100
advert_int 1
virtual_ipaddress {
192.168.18.100/24 dev ens33
}
authentication {
auth_type PASS
auth_pass password
}
track_script {
checkhaproxy
}
}
主要参数在vrrp_instance段中进行设置,说明如下。
- vrrp_instance VI_1:设置keepalived虚拟路由器VRRP的名称。
- state:设置为“MASTER”,将其他keepalived均设置为“BACKUP”。
- interface:待设置VIP地址的网卡名称。
- virtual_router_id:例如51。
- priority:优先级,例如100。
- virtual_ipaddress:VIP地址,例如192.168.18.100/24。
- authentication:访问keepalived服务的鉴权信息。
- track_script:HAProxy健康检查脚本。
Keepalived需要持续监控HAProxy的运行状态,在某个HAProxy实例运行不正常时,自动切换到运行正常的HAProxy实例上。需要创建一个HAProxy健康检查脚本,定期运行该脚本进行监控,例如新建脚本check-haproxy.sh并将其保存到/usr/bin目录下,内容示例如下:
#!bin/bash
count=`netstat -apn | grep 9443 | wc -l`
if [ $count -gt 0 ]; then
exit 0
else
exit 1
fi
若检查成功,则应返回0;若检查失败,则返回非0值。Keepalived根据上面的配置,会每隔2s检查一次HAProxy的运行状态。例如,如果在192.168.18.3 上检查失败,keepalived就会将VIP地址切换到正常运行HAProxy的192.168.18.4服务器上,保证VIP 192.168.18.100地址的高可用
在第2台服务器192.168.18.4上创建配置文件keepalived.conf,内容示例如下:
! Configuration File for keepalived
global_defs {
router_id LVS_2
}
vrrp_script checkhaproxy
{
script "/usr/bin/check-haproxy.sh"
interval 2
weight -30
}
vrrp_instance VI_1 {
state BACKUP
interface ens33
virtual_router_id 51
priority 100
advert_int 1
virtual_ipaddress {
192.168.18.100/24 dev ens33
}
authentication {
auth_type PASS
auth_pass password
}
track_script {
checkhaproxy
}
}
这里与第1个keepalived配置的主要差异如下。
- vrrp_instance中的state被设置为“BACKUP”,这是因为在整个keepalived集群中只能有一个被设置为“MASTER”。如果keepalived集群不止2个实例,那么除了MASTER,其他都应被设置为“BACKUP”。
- vrrp_instance的值“VI_1”需要与MASTER的配置相同,表示它们属于同一个虚拟路由器组(VRRP),当MASTER不可用时,同组的其他BACKUP实例会自动选举出一个新的MASTER。
- HAProxy健康检查脚本check-haproxy.sh与第1个keepalived的相同。
下面以Docker容器方式运行HAProxy且镜像使用osixia/keepalived为例进行说明。在两台服务器192.168.18.3和192.168.18.4上启动HAProxy,将配置文件keepalived.conf挂载到容器的/container/service/keepalived/assets目录下,启动命令如下:
[root@k8s-m01 ~]# docker run -d --name k8s-keepalived \
--restart=always \
--net=host \
--cap-add=NET_ADMIN --cap-add=NET_BROADCAST --cap-add=NET_RAW \
-v ${PWD}/keeppalived.conf:/container/service/keepalived/assets/keepalived.conf \
-v ${PWD}/check-haproxy.sh:/usr/bin/check-haproxy.sh \
osixia/keepalived:2.0.20 --copy-service
在运行正常的情况下,keepalived会在服务器192.168.18.3的网卡ens33上设置192.168.18.100的IP地址,同样在服务器192.168.18.3上运行的HAProxy将在该IP地址上监听9443端口号,对需要访问Kubernetes Master的客户端提供负载均衡器的入口地址,即192.168.18.100:9443。
通过ip addr命令查看服务器192.168.18.3的IP地址信息,可以看到在ens33网卡上新增了192.168.18.100地址:
使用curl命令即可验证通过HAProxy的192.168.18.100:9443地址是否可以访问到kube-apiserver服务:
[root@k8s-m01 ~]# curl -v -k https://192.168.18.100:9443
可以看到TCP/IP连接创建成功,得到响应码为401的应答,说明通过VIP地址192.168.18.100成功访问到了后端的kube-apiserver服务。至此,Master上所需的3个服务就全部启动完成了。接下来就可以部署Node的服务了。
5.部署Node的服务
Node上需要部署Docker、kubelet、kube-proxy,在成功加入Kubernetes集群后,还需要部署CNI网络插件、DNS插件等管理组件。Docker的安装和启动详见Docker官网的说明文档。本节主要对如何部署kubelet和kube-proxy进行说明。CNI网络插件的安装部署详见7.7节的说明,DNS插件的安装部署详见4.3节的说明。
本节以将192.168.18.3、192.168.18.4和192.168.18.5三台主机部署为Node为例进行说明,由于这三台主机都是Master节点,所以最终部署结果为一个包含三个Node节点的Kubernetes集群。
1.部署kubelet服务
(1)为kubelet服务创建systemd服务配置文件/usr/lib/systemd/system/kubelet.service,内容如下:
[Unit]
Description=Kubernetes Kubelet
Documentation=https://github.com/kubernetes/kubernetes
After=docker.target
[Service]
EnvironmentFile=/etc/kubernetes/kubelet
ExecStart=/usr/bin/kubelet $KUBELET_ARGS
Restart=always
[Install]
WantedBy=multi-user.target
(2)配置文件/etc/kubernetes/kubelet的内容为通过环境变量KUBELET_ARGS设置的kubelet的全部启动参数,示例如下:
KUBELET_ARGS="--kubeconfig=/etc/kubernetes/kubeconfig \
--config=/etc/kubernetes/kubelet.config \
--hostname-override=192.168.18.3 \
--network-plugin=cni \
--logtostderr=false --log-dir=/var/log/kubernetes --v=0"
对主要参数说明如下。
- --kubeconfig:设置与API Server连接的相关配置,可以与kube-controller-manager使用的kubeconfig文件相同。需要将相关客户端证书文件从Master主机复制到Node主机的/etc/kubernetes/pki目录下,例如ca.crt、client.key、client.crt文件。
- --config:kubelet配置文件,从Kubernetes 1.10版本开始引入,设置可以让多个Node共享的配置参数,例如address、port、cgroupDriver、clusterDNS、clusterDomain等。关于kubelet.config文件中可以设置的参数内容和详细说明,请参见官方文档的说明。
- --hostname-override:设置本Node在集群中的名称,默认值为主机名,应将各Node设置为本机IP或域名。
- --network-plugin:网络插件类型,建议使用CNI网络插件。
配置文件kubelet.config的内容示例如下:
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
address: 0.0.0.0
port: 10250
cgroupDriver: cgroupfs
clusterDNS: ["169.169.0.100"]
clusterDomain: cluster.local
authentication:
anonymous:
enabled: true
在本例中设置的kubelet参数如下。
◎ address:服务监听IP地址。
◎ port:服务监听端口号,默认值为10250。
◎ cgroupDriver:设置为cgroupDriver驱动,默认值为cgroupfs,可选项包括systemd。
◎ clusterDNS:集群DNS服务的IP地址,例如169.169.0.100。
◎ clusterDomain:服务DNS域名后缀,例如cluster.local。
◎ authentication:设置是否允许匿名访问或者是否使用webhook进行鉴权。
(3)在配置文件准备完毕后,在各Node主机上启动kubelet服务并设置为开机自启动:
[root@k8s-m01 ~]# systemctl start kubelet && systemctl enable kubelet
2.部署kube-proxy服务
(1)为kube-proxy服务创建systemd服务配置文件/usr/lib/systemd/system/kube-proxy.service,内容如下:
[Unit]
Description=Kubernetes Kube-Proxy Server
Documentation=https://github.com/kubernetes/kubernetes
After=network.target
[Service]
EnvironmentFile=/etc/kubernetes/proxy
ExecStart=/usr/bin/kube-proxy $KUBE_PROXY_ARGS
Restart=always
[Install]
WantedBy=multi-user.target
(2)配置文件/etc/kubernetes/proxy的内容为通过环境变量KUBE_PROXY_ARGS设置的kube-proxy的全部启动参数,示例如下:
KUBE_PROXY_ARGS="--kubeconfig=/etc/kubernetes/kubeconfig \
--hostname-override=192.168.18.3 \
--proxy-mode=iptables \
--logtostderr=false --log-dir=/var/log/kubernetes --v=0"
对主要参数说明如下。
- --kubeconfig:设置与API Server连接的相关配置,可以与kubelet使用的kubeconfig文件相同。相关客户端CA证书使用部署kubelet服务时从Master主机复制到Node主机的/etc/kubernetes/pki目录下的文件,包括ca.crt、client.key和client.crt。
- --hostname-override:设置本Node在集群中的名称,默认值为主机名,各Node应被设置为本机IP或域名。
- --proxy-mode:代理模式,包括iptables、ipvs、kernelspace(Windows节点使用)等。
(3)在配置文件准备完毕后,在各Node主机上启动kube-proxy服务,并设置为开机自启动:
[root@k8s-m01 ~]# systemctl start kube-proxy && systemctl enable kube-proxy
3.在Master上通过kubectl验证Node信息
在各个Node的kubelet和kube-proxy服务正常启动之后,会将本Node自动注册到Master上,然后就可以到Master主机上通过kubectl查询自动注册到Kubernetes集群的Node的信息了。
由于Master开启了HTTPS认证,所以kubectl也需要使用客户端CA证书连接Master,可以直接使用kube-controller-manager的kubeconfig文件,命令如下:
[root@k8s-m01 ~]# kubectl --kubeconfig=/etc/kubernetes/kubeconfig get nodes
我们可以看到各Node的状态为“NotReady”,这是因为还没有部署CNI网络插件,无法设置容器网络。
类似于通过kubeadm创建Kubernetes集群,例如选择Calico CNI插件运行下面的命令一键完成CNI网络插件的部署:
[root@k8s-m01 ~]# kubectl apply -f "https://docs.projectcalico.org/manifests/calico.yaml"
在CNI网络插件成功运行之后,Node的状态会更新为“Ready”:
[root@k8s-m01 ~]# kubectl --kubeconfig=/etc/kubernetes/kubeconfig get nodes
为了使Kubernetes集群正常工作,我们还需要部署DNS服务,建议使用CoreDNS进行部署。
至此,一个有三个Master节点的高可用Kubernetes集群就部署完成了,接下来用户就可以创建Pod、Deployment、Service等资源对象来部署、管理容器应用和微服务了。
本节对Kubernetes各服务启动进程的关键配置参数进行了简要说明,实际上Kubernetes的每个服务都提供了许多可配置的参数。这些参数涉及安全性、性能优化及功能扩展等方方面面。全面理解和掌握这些参数的含义和配置,对Kubernetes的生产部署及日常运维都有很大帮助。对各服务配置参数的详细说明参见附录。
6.kube-apiserver基于token的认证机制
Kubernetes除了提供了基于CA证书的认证方式,也提供了基于HTTP Token的简单认证方式。各客户端组件与API Server之间的通信方式仍然采用HTTPS,但不采用CA数字证书。这种认证机制与CA证书相比,安全性很低,在生产环境不建议使用。
采用基于HTTP Token的简单认证方式时,API Server对外暴露HTTPS端口,客户端携带Token来完成认证过程。需要说明的是,kubectl命令行工具比较特殊,它同时支持CA证书和简单认证两种方式与API Server通信,其他客户端组件只能配置基于CA证书的认证方式或者非安全方式与API Server通信。
基于Token认证的配置过程如下。
(1)创建包括用户名、密码和UID的文件token_auth_file,将其放置在合适的目录下,例如/etc/kuberntes目录。需要注意的是,这是一个纯文本文件,用户名、密码都是明文。
[root@k8s-m01 ~]# cat /etc/kubernetes/token_auth_file
admin,admin,1
system,system,2
(2)设置kube-apiserver的启动参数“--token-auth-file”,使用上述文件提供安全认证,然后重启API Server服务。
--secure-port=6443
--token-auth-file=/etc/kubernetes/token_auth_file
(3)用curl客户端工具通过token访问API Server:
[root@k8s-m01 ~]# curl -k --header "Authorization:Bearer admin https://192.168.18.3:6443/version"
四.使用私有镜像库的相关配置
在Kubernetes集群中,容器应用都是基于镜像启动的,在私有云环境中建议搭建私有镜像库对镜像进行统一管理,在公有云环境中可以直接使用云服务商提供的镜像库。
私有镜像库有两种选择。
- Docker提供的Registry镜像库,详细说明请参考官网的说明。
- Harbor镜像仓库,详细说明请参考官网的说明或者Harbor项目维护者及贡献者编写的《Harbor权威指南》一书。
此外,Kubernetes对于创建Pod需要使用一个名为“pause”的镜像,tag名为“k8s.gcr.io/pause:3.2”,默认从镜像库k8s.gcr.io下载,在私有云环境中可以将其上传到私有镜像库,并修改kubelet的启动参数--pod-infra-container-image,将其设置为使用镜像库的镜像名称,例如:
--pod-infra-container-image=<my-private-registry>/pause:3.2
五.Kubernetes的版本升级
1.二进制文件升级
在进行Kubernetes的版本升级之前,需要考虑不中断正在运行的业务容器的灰度升级方案。常见的做法是:先更新Master上Kubernetes服务的版本,再逐个或批量更新集群中的Node上Kubernetes服务的版本。更新Node的Kubernetes服务的步骤通常包括:先隔离一个或多个Node的业务流量,等待这些Node上运行的Pod将当前任务全部执行完成后,停掉业务应用(Pod),再更新这些Node上的kubelet和kube-proxy版本,更新完成后重启业务应用(Pod),并将业务流量导入新启动的这些Node上,再隔离剩余的Node,逐步完成Node的版本升级,最终完成整个集群的Kubernetes版本升级。
同时,应该考虑高版本的Master对低版本的Node的兼容性问题。高版本的Master通常可以管理低版本的Node,但版本差异不应过大,以免某些功能或API版本被弃用后,低版本的Node无法运行。
- 通过官网获取最新版本的二进制包kubernetes.tar.gz,解压后提取服务的二进制文件。
- 更新Master的kube-apiserver、kube-controller-manager、kube-scheduler服务的二进制文件和相关配置(在需要修改时更新)并重启服务。
- 逐个或批量隔离Node,等待其上运行的全部容器工作完成后停掉Pod,更新kubelet、kube-proxy服务文件和相关配置(在需要修改时更新),然后重启这两个服务。
2.使用kubeadm进行集群升级
kubeadm提供了upgrade命令用于对kubeadm安装的Kubernetes集群进行升级。这一功能提供了从1.10到1.11、从1.11到1.12、从1.12到1.13及从1.13到1.14升级的能力,本节以从1.13到1.14升级为例进行说明。
升级之前需要注意:
- 虽然kubeadm的升级不会触及工作负载,但还是要在升级之前做好备份;
- 升级过程中可能会因为Pod的变化而造成容器重启。
继续以CentOS 7环境为例,首先需要升级的是kubeadm:
[root@k8s-m01 ~]# yum install -y kubeadm-1.14.0 --disableexcludes=kubernetes
查看kubeadm的版本
[root@k8s-m01 ~]# kubeadm version
接下来查看kubeadm的升级计划:
[root@k8s-m01 ~]# kubeadm upgrade plan
会出现预备升级的内容描述,按照任务指引进行升级
[root@k8s-m01 ~]# kubeadm upgrade apply 1.14.0
输入“y”,确认后开始升级。
运行完成之后,再次查询版本:
[root@k8s-m01 ~]# kubectl version
可以看到,虽然kubectl还是1.13.2,服务端的控制平面已经升级到了1.14.0,但是查看Node版本,会发现Node版本还是滞后的,然后可以对节点配置进行升级:
[root@k8s-m01 ~]# kubeadm upgrade node config --kubelet-version 1.14.0
接下来,直接下载新版本的kubectl二进制文件,用其覆盖旧版本的文件来完成kubectl的升级,这样就完成了集群的整体升级。
六.CRI(容器运行时接口)详解
归根结底,Kubernetes Node(kubelet)的主要功能就是启动和停止容器的组件,我们称之为容器运行时(Container Runtime),其中最知名的就是Docker了。为了更具扩展性,Kubernetes从1.5版本开始就加入了容器运行时插件API,即Container Runtime Interface,简称CRI。
1.CRI概述
每个容器运行时都有特点,因此不少用户希望Kubernetes能够支持更多的容器运行时。Kubernetes从1.5版本开始引入了CRI接口规范,通过插件接口模式,Kubernetes无须重新编译就可以使用更多的容器运行时。CRI包含Protocol Buffers、gRPC API、运行库支持及开发中的标准规范和工具。Docker的CRI实现在Kubernetes 1.6中被更新为Beta版本,并在kubelet启动时默认启动。
可替代的容器运行时支持是Kubernetes中的新概念。在Kubernetes 1.3发布时,rktnetes项目同时发布,让rkt容器引擎成为除Docker外的又一选择。然而,不管是Docker还是rkt,都用到了kubelet的内部接口,同kubelet源码纠缠不清。这种程度的集成需要对kubelet的内部机制有非常深入的了解,还会给社区带来管理压力,这就给新生代容器运行时造成了难以跨越的集成壁垒。CRI接口规范尝试用定义清晰的抽象层清除这一壁垒,让开发者能够专注于容器运行时本身。
2.CRI的主要组件
kubelet使用gRPC框架通过UNIX Socket与容器运行时(或CRI代理)进行通信。在这个过程中kubelet是客户端,CRI代理(shim)是服务端,如图2.7所示。
Protocol Buffers API包含两个gRPC服务:ImageService和RuntimeService。
- ImageService提供了从仓库中拉取镜像、查看和移除镜像的功能。
- RuntimeService负责Pod和容器的生命周期管理,以及与容器的交互(exec/attach/port-forward)。rkt和Docker这样的容器运行时可以使用一个Socket同时提供两个服务,在kubelet中可以用--container-runtime-endpoint和--image-service-endpoint参数设置这个Socket。
3.Pod和容器的生命周期管理
Pod由一组应用容器组成,其中包含共有的环境和资源约束。在CRI里,这个环境被称为PodSandbox。Kubernetes有意为容器运行时留下一些发挥空间,它们可以根据自己的内部实现来解释PodSandbox。对于Hypervisor类的运行时,PodSandbox会具体化为一个虚拟机。其他例如Docker,会是一个Linux命名空间。在v1alpha1 API中,kubelet会创建Pod级别的cgroup传递给容器运行时,并以此运行所有进程来满足PodSandbox对Pod的资源保障。
在启动Pod之前,kubelet调用RuntimeService.RunPodSandbox来创建环境。这一过程包括为Pod设置网络资源(分配IP等操作)。PodSandbox被激活之后,就可以独立地创建、启动、停止和删除不同的容器了。kubelet会在停止和删除PodSandbox之前首先停止和删除其中的容器。
kubelet的职责在于通过RPC管理容器的生命周期,实现容器生命周期的钩子、存活和健康监测,以及执行Pod的重启策略等。
RuntimeService服务包括对Sandbox和Container操作的方法,下面的伪代码展示了主要的RPC方法:
service RuntimeService {
## 沙箱操作
rpc RunPodSandbox(RunPodSandboxRequest) returns(RunPodSandboxResponse) {}
rpc StopPodSandbox(StopPodSandboxRequest) returns(StopPodSandboxResponse) {}
rpc RemovePodSandbox(RemovePodSandboxRequest) returns(RemovePodSandboxResponse) {}
rpc PodSandboxStatus(RunPodSandboxStatusRequest) returns(RunPodSandboxStatusResponse) {}
rpc ListPodSandbox(ListPodSandboxRequest) returns(ListPodSandboxResponse) {}
## 容器操作
rpc CreateContainer(CreateContainerRequest) returns(CreateContainerResponse) {}
rpc StartContainer(StartContainerRequest) returns(StartContainerResponse) {}
rpc StopContainer(StopContainerRequest) returns(StopContainerResponse) {}
rpc RemoveContainer(RmoveContainerRequest) returns(RemoveContainerResponse) {}
rpc ListContainer(ListContainerRequest) returns(ListContainerResponse) {}
rpc ContainerStatus(ContainerStatusRequest) returns(ContainerStatusResponse) {}
......
}
4.面向容器级别的设计思路
众所周知,Kubernetes的最小调度单元是Pod,它曾经可能采用的一个CRI设计就是复用Pod对象,使得容器运行时可以自行实现控制逻辑和状态转换,这样一来,就能极大地简化API,让CRI能够更广泛地适用于多种容器运行时。但是经过深入讨论之后,Kubernetes放弃了这一想法。
首先,kubelet有很多Pod级别的功能和机制(例如crash-loop backoff机制),如果交给容器运行时去实现,则会造成很重的负担;然后,Pod标准还在快速演进。很多新功能(如初始化容器)都是由kubelet完成管理的,无须交给容器运行时实现。
CRI选择了在容器级别进行实现,使得容器运行时能够共享这些通用特性,以获得更快的开发速度。这并不意味着设计哲学的改变—kubelet要负责、保证容器应用的实际状态和声明状态的一致性。
Kubernetes为用户提供了与Pod及其中的容器进行交互的功能(kubectl exec/attach/port-forward)。kubelet目前提供了两种方式来支持这些功能:①调用容器的本地方法;②使用Node上的工具(例如nsenter及socat)。
因为多数工具都假设Pod用Linux namespace做了隔离,因此使用Node上的工具并不是一种容易移植的方案。在CRI中显式定义了这些调用方法,让容器运行时进行具体实现。下面的伪代码显示了Exec、Attach、PortForward这几个调用需要实现的RuntimeService方法:
service RuntimeService{
......
## ExecSync在容器中同步运行一个命令
rpc ExecSync(ExecSyncRequest) returns(ExecSyncResponse) {}
## Exec在容器中运行命令
rpc Exec(ExecRequest) returns(ExecResponse) {}
## Attach附着在容器上
rpc Attach(AttachRequest) returns(AttachResponse) {}
## PortForward从Pod沙箱中进行端口转发
rpc PortForward(PortForwardRequest) returns(PortForwardResponse) {}
......
}
目前还有一个潜在的问题是,kubelet处理所有的请求连接,使其有成为Node通信瓶颈的可能。在设计CRI时,要让容器运行时能够跳过中间过程。容器运行时可以启动一个单独的流式服务来处理请求(还能对Pod的资源使用情况进行记录),并将服务地址返回给kubelet。这样kubelet就能反馈信息给API Server,使之可以直接连接到容器运行时提供的服务,并连接到客户端。
5.尝试使用新的Docker-CRI来创建容器
要尝试新的kubelet-CRI-Docker集成,只需为kubelet启动参数加上--enable-cri=true开关来启动CRI。这个选项从Kubernetes 1.6开始已经作为kubelet的默认选项了。如果不希望使用CRI,则可以设置--enable-cri=false来关闭这个功能。
查看kubelet的日志,可以看到启用CRI和创建gRPC Server的日志
创建一个Deployment:
[root@k8s-m01 ~]# kubectl run nginx --image=nginx
查看Pod的详细信息,可以看到将会创建沙箱(Sandbox)的Event:
[root@k8s-m01 ~]# kubectl describe pod nginx
这表明kubelet使用了CRI接口来创建容器。
目前已经有多款开源CRI项目可用于Kubernetes:Docker、CRI-O、Containerd、frakti(基于Hypervisor的容器运行时),各CRI运行时的安装手册可参考官网的说明。
七.Kubectl命令行工具用法详解
kubectl作为客户端CLI工具,可以让用户通过命令行对Kubernetes集群进行操作。本节对kubectl的子命令和用法进行详细说明。
1.kubectl用法概述
kubectl命令行的语法如下:
[root@k8s-m01 ~]# kubectl [command] [TYPE] [NAME] [flags]
其中,command、TYPE、NAME、flags的含义如下。
(1)command:子命令,用于操作资源对象,例如create、get、describe、delete等。
(2)TYPE:资源对象的类型,区分大小写,能以单数、复数或者简写形式表示。例如以下3种TYPE是等价的。
[root@k8s-m01 ~]# kubectl get pod pod1
[root@k8s-m01 ~]# kubectl get pods pod1
[root@k8s-m01 ~]# kubectl get po pod1
(3)NAME:资源对象的名称,区分大小写。如果不指定名称,系统则将返回属于TYPE的全部对象的列表,例如运行kubectl get pods命令后将返回所有Pod的列表。
在一个命令行中也可以同时对多个资源对象进行操作,以多个TYPE和NAME的组合表示,示例如下。
获取多个相同类型资源的信息,以TYPE1 name1 name2 name<#>格式表示:
[root@k8s-m01 ~]# kubectl get pod example-pod1 example-pod2
获取多种不同类型对象的信息,以TYPE1/name1 TYPE1/name2 TYPE2/name3 TYPE<#>/name<#>格式表示:
[root@k8s-m01 ~]# kubectl get pod/example-pod1 replicationcontroller/example-rc1
同时应用多个YAML文件,以多个-f file参数表示:
[root@k8s-m01 ~]# kubectl get pod -f pod1.yaml -f pod2.yaml
[root@k8s-m01 ~]# kubectl create -f pod1.yaml -f rc.yaml -f service1.yaml
(4)flags:kubectl子命令的可选参数,例如使用-s或--server设置API Server的URL地址,而不使用默认值。
2.kubectl子命令详解
3.kubectl可操作的中资源对象详解
kubectl可操作的资源对象列表如表所示,可以通过kubectl api-resources命令进行查看。
Kubectl的公共参数说明
每个子命令(如create、delete、get等)还有其特定的命令行参数,可以通过$ kubectl [command]--help命令进行查看。
5.Kubectl格式化输出
kubectl命令可以对结果进行多种格式化显示,输出的格式通过-o参数指定:
[root@k8s-m01 ~]# kubectl [command] [TYPE] [NAME] -o=<output_format>
根据不同子命令的输出结果,可选的输出格式如表所示
常用的输出格式示例如下
(1)显示Pod的更多信息,例如Node IP等:
[root@k8s-m01 ~]# kubectl get pod <pod-name> -o wide
(2)以YAML格式显示Pod的详细信息:
[root@k8s-m01 ~]# kubectl get pod <pod-name> -o yaml
(3)以自定义列名显示Pod的信息:
[root@k8s-m01 ~]# kubectl get pod <pod-name> -o custom-columns=NAME:.metadata.name,RSRC:.metadata.resourceVersion
(3)以自定义列名显示Pod的信息:
[root@k8s-m01 ~]# kubectl get pod <pod-name> -o custom-columns-file=template.txt
template.txt文件的内容如下:
NAME RSRC
metadata.name metadata.resourceVersion
输出结果如下
NAME RSRC
pod-name 52305
(5)关闭服务端列名。在默认情况下,Kubernetes服务端会将资源对象的某些特定信息显示为列,这可以通过设置--server-print=false参数进行关闭,例如:
[root@k8s-m01 ~]# kubectl get pods <pod-name> --server-print=false
输出结果:
NAME AGE
pod-name 1m
(6)将输出结果按某个字段排序。可以通过--sort-by参数以jsonpath表达式进行指定:
[root@k8s-m01 ~]# kubectl [command] [TYPE] [NAME] --sort-by=<jsonpath-exp>
例如,按照资源对象的名称进行排序:
[root@k8s-m01 ~]# kubectl get pods --sort-by=.metadata.name
6.Kubectl常用操作示例
本节对一些常用的kubectl操作示例进行说明。
1.kubectl apply(以文件或stdin部署或更新一个或多个资源)
基于example-service.yaml中的定义创建一个Service资源:
[root@k8s-m01 ~]# kubectl apply -f example-service.yaml
使用example-controller.yaml中的定义创建一个Replication Controller资源:
[root@k8s-m01 ~]# kubectl apply -f example-controller.yaml
使用
[root@k8s-m01 ~]# kubectl apply -f <directory>
2..kubectl get(列出一个或多个资源对象的信息)
以文本格式列出所有Pod:
[root@k8s-m01 ~]# kubectl get pods
以文本格式列出所有Pod,包含附加信息(如Node IP):
[root@k8s-m01 ~]# kubectl get pods -o wide
以文本格式列出指定名称的RC:
[root@k8s-m01 ~]# kubectl get replicationcontroller <rc-name>
以文本格式列出所有RC和Service:
[root@k8s-m01 ~]# kubectl get rc,services
以文本格式列出所有Daemonset,包括未初始化的Daemonset:
[root@k8s-m01 ~]# kubectl get ds --include-uninitialized
列出在节点server01上运行的所有Pod:
[root@k8s-m01 ~]# kubectl get pods --field-selector=spec.nodeName=server01
3.kubectl describe(显示一个或多个资源的详细信息)
显示名称为
[root@k8s-m01 ~]# kubectl describe nodes <node-name>
显示名称为
[root@k8s-m01 ~]# kubectl describe pods/<node-name>
显示名称为
[root@k8s-m01 ~]# kubectl describe pods <rc-name>
描述所有Pod的详细信息:
[root@k8s-m01 ~]# kubectl describe pods
对kubectl get和kubectl describe命令说明如下。
◎ kubectl get命令常用于查看同一资源类型的一个或多个资源对象,可以使用-o或--output参数自定义输出格式,还可以通过-w或--watch参数开启对资源对象更新的监控。
◎ kubectl describe命令更侧重于描述指定资源的各方面详细信息,通过对API Server的多个API调用来构建结果视图。例如通过kubectl describe node命令不仅会返回节点信息,还会返回在其上运行的Pod的摘要、节点事件等信息。
4.kubectl delete
该命令可以使用文件、stdin的输入删除指定的资源对象,还可以通过标签选择器、名称、资源选择器等条件来限定待删除的资源范围
使用在pod.yaml文件中指定的类型和名称删除Pod:
[root@k8s-m01 ~]# kubectl delete -f pod.yaml
删除所有带有'
[root@k8s-m01 ~]# kubectl delete pods,services -l <label-key>=<label-value>
删除所有Pod,包括未初始化的Pod:
[root@k8s-m01 ~]# kubectl delete pods --all
5.kubectl exec(在Pod的容器中运行命令)
在名称为
[root@k8s-m01 ~]# kubectl exec <pod-name> -- date
在Pod的第1个容器中运行/bin/bash命令进入交互式TTY终端界面:
[root@k8s-m01 ~]# kubectl exec -it <pod-name> -- /bin/bash
6.kubectl logs(打印Pod中容器的日志)
[root@k8s-m01 ~]# kubectl logs <pod-name>
显示Pod中名称为
[root@k8s-m01 ~]# kubectl logs <pod-name> -c <container-name>
持续监控显示Pod中的第1个容器输出到stdout的日志,类似于tail-f命令的功能:
[root@k8s-m01 ~]# kubectl logs -f <pod-name>
7. 在线编辑运行中的资源对象
可以使用kubectl edit命令编辑运行中的资源对象,例如使用下面的命令编辑运行中的一个Deployment:
[root@k8s-m01 ~]# kubectl edit deploy nginx
在命令运行之后,会通过YAML格式展示该对象的文本格式定义,用户可以对代码进行编辑和保存,从而完成对在线资源的直接修改。
8. 将Pod的端口号映射到宿主机
将Pod的80端口映射到宿主机的8888端口,客户端即可通过http://
[root@k8s-m01 ~]# kubectl port-forward --address 0.0.0.0 \
pod/nginx-6ddbbc47fb-sfdcv 8888:80
9.在容器和Node之间复制文件
把Pod(默认为第1个容器)中的/etc/fstab文件复制到宿主机的/tmp目录下:
[root@k8s-m01 ~]# kubectl cp nginx-6ddbbc47fb-sfdcv:/etc/fstab /tmp
10 设置资源对象的标签
为名为“default”的命名空间设置“testing=true”标签:
[root@k8s-m01 ~]# kubectl label namespaces default texting=true
11.创建和使用命令行插件
为了扩展kubectl的功能,Kubernetes从1.8版本开始引入插件机制,在1.14版本时达到稳定版。
用户自定义插件的可执行文件名需要以“kubectl-”开头,复制到$PATH中的某个目录(如/usr/local/bin)下,然后就可以通过kubectl
例如,通过Shell脚本实现一个名为hello的插件,其功能为在屏幕上输出字符串“hello world”。创建名为“kubectl-hello”的Shell脚本文件,内容如下:
#!/bin/sh
echo "hello world"
为该脚本添加可执行权限:
[root@k8s-m01 ~]# chmod a+x ./kubectl-hello
复制kubectl-hello文件到/usr/local/bin/目录下,就完成了安装插件的工作:
[root@k8s-m01 ~]# cp ./kubectl-hello /usr/local/bin
卸载插件也很简单,只需要删除插件文件即可:
[root@k8s-m01 ~]# rm /usr/local/bin/kubectl-hello
通过插件机制,可以将某些复杂的kubectl命令简化为运行插件的方式。例如想创建一个命令来查看当前上下文环境(context)中的用户名,则可以通过kubectl config view命令进行查看。为此,可以创建一个名为“kubectl-whoami”的Shell脚本,内容如下:
#!/bin/bash
kubectl config view --template='{{ range .contexts }}{{ if eq .name "'$(kubectl config current-context)'" }}Current user: {{ .context.user }}{{ end }}{{ end }}'
为该脚本添加可执行权限,并复制到/usr/local/bin/目录下完成插件的安装:
[root@k8s-m01 ~]# chmod a+x ./kubectl-whoami
[root@k8s-m01 ~]# cp ./kubectl-whoami /usr/local/bin
运行kubectl whoami命令,就能通过插件功能查看上下文环境中的用户名了:
[root@k8s-m01 bin]# kubectl whoami
Current user: kubernetes-admin
另外,使用kubectl plugin list命令可以查看当前系统中已安装的插件列表:
[root@k8s-m01 bin]# kubectl plugin list
The following compatible plugins are available:
/usr/local/bin/kubectl-hello