说明:由于最近计划开展K8S及容器的安全评估,但是对于K8S的组件、规划及部署不是很清楚,对于K8S的安全评估存在更多的知识盲区,因此我从网络中找了相关的视频进行了学习,并同步进行了实验学习。本篇是一个K8S的简单部署学习笔记,在网上能够找到更加详细、类似的文章,在学习实验的过程中也遇到一些问题,在这个过程中通过各种方法进行了解决,增加了对相应知识点的理解。笔者计划先跟着老师将实验完成,先实操一遍,再回头看看架构、原因、以及在这个过程中遇到的问题。
一、集群规划:
Master
主机名:k8s-master1
IP:192.168.2.151
Worker1
主机名:k8s-worker1
IP:192.168.2.153
Worker2
主机名:k8s-worker2
IP:192.168.2.154
Etcd:
IP:192.168.2.151
IP:192.168.2.153
IP:192.168.2.154
K8版本:1.16
安装方式:二进制离线安装
操作系统版本:CentOS Linux release 7.6.1810 (Core)
二、初始化服务器
1、关闭防火墙
2、关闭selinux
3、配置主机名
4、配置名称解析
5、配置时间同步
6、关闭交换分区
三、给ETCD颁发证书
可以使用OpenSSL及Cfssl工具签发证书,其中cfssl是cloudflare开发的一款证书管理工具,可以用于签发、验证等,现cfssl已经作为K8S证书管理中的配套工具,详细的说明介绍及工具下载可以查看GITHUB网站:
https://github.com/cloudflare/cfssl
如何生成etcd的证书可以参考如下的链接:
https://kubernetes.io/docs/tasks/administer-cluster/certificates/
1、生成配置文件以及csr请求文件,文件均为json格式
cfssl print-defaults config > config.json
cfssl print-defaults csr > csr.json
2、通过csr请求文件生成CA证书及CA私钥:
cfssl gencert -initca csr.json | cfssljson -bare ca
此时生成了ca.pem公钥文件及ca-key.pem私钥文件。
3、创建一个server-csr.json文件,该文件是etcd服务器的证书请求文件,其中hosts文件应该包含etcd服务器的IP地址,如下:
[root@k8s-master1 etcd-cert]# cat server-csr.json
{
"CN": "example.net",
"hosts": [
"192.168.2.151",
"192.168.2.153",
"192.168.2.154"
],
"key": {
"algo": "ecdsa",
"size": 256
},
"names": [
{
"C": "US",
"L": "CA",
"ST": "San Francisco"
}
]
}
4、通过根证书为etcd服务器创建服务器证书文件:
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem --config=config.json -profile=www server-csr.json | cfssljson -bare server
可以看到生成了server-key.pem,server.pem文件。
四、部署etcd
现在在master、worker1、worker2上分别安装etcd。通过etcd包解压进行安装,解压之后生成一个etcd.service文件,该文件为system启动文件,另外生成一个etcd相关的目录。
1、将etcd.service拷贝至/usr/lib/systemd/system目录
2、修改etcd的配置文件:/opt/etcd/cfg/etcd.conf,配置内容如下:
[root@k8s-master1 etcd-cert]# cat /opt/etcd/cfg/etcd.conf
#[Member]
ETCD_NAME="etcd-1"
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="https://192.168.2.151:2380"
ETCD_LISTEN_CLIENT_URLS="https://192.168.2.151:2379"
#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.2.151:2380"
ETCD_ADVERTISE_CLIENT_URLS="https://192.168.2.151:2379"
ETCD_INITIAL_CLUSTER="etcd-1=https://192.168.2.151:2380,etcd-2=https://192.168.2.153:2380,etcd-3=https://192.168.2.154:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"
3、将前面生成的ca.pem、server.pem、server-key.pem拷贝至/opt/etcd/ssh/目录下:
# cp -fv ca.pem server.pem server-key.pem /opt/etcd/ssl/
4、在worker1、worker2上按照上面的步骤部署etcd服务,可以将master上的etcd文件拷贝至worker1、worker2,并在worker1、worker2上面修改etcd.conf配置文件,主要修改Member部分内容:
Worker1如下:
Worker2如下:
5、在三个节点上启用etcd服务
# systemctl start etcd
# systemctl enable etcd
6、检查是否启动成功:
/opt/etcd/bin/etcdctl --ca-file=/opt/etcd/ssl/ca.pem --cert-file=/opt/etcd/ssl/server.pem --key-file=/opt/etcd/ssl/server-key.pem --endpoints="https://192.168.2.151:2379,https://192.168.2.153:2379,https://192.168.2.154:2379" cluster-health
五、为API Server签发SSL证书
签发证书的步骤与第三步一样,不再赘述。
六、部署Master服务
在K8S的管理体系中,需要在master部署apiserver、controller-manager、scheduler服务,在worker上部署docker、kubectl、kube-proxy服务。
1、解压k8s-master包,将kube-apiserver.service、kube-controller-manager.service、kube-scheduler.service服务拷贝至/usr/lib/systemd/system/作为系统服务
2、将kubernetes拷贝至/opt目录下,并且将证书文件拷贝至其/ssl目录下:
cp /root/TLS/k8s/{ca*pem,server.pem,server-key.pem} /opt/kubernetes/ssl/ -rvf
3、修改apiserver的配置文件
注意配置/etcd-servers参数,同时注意下面证书的路径。
4、启动master服务
# cp /opt/kubernetes/bin/kubectl /bin/
# systemctl start kube-apiserver
# systemctl enable kube-apiserver
# systemctl enable kube-scheduler
# systemctl start kube-scheduler
# systemctl start kube-controller-manager
# systemctl enable kube-controller-manager
5、查看启动结果
1)可以查看进程:ps -ef | grep kube
2)可以查看集群信息:
kubectl get cs
6、配置tls 基于bootstrap自动颁发证书
# kubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --user=kubelet-bootstrap
七、安装worker node节点相关服务
在workder node上需要安装docker容器、配置kubelet以及kube-proxy,kubelet用于接受APIServer的指令,然后控制docker容器;Kube-proxy为worker上的容器配置网络服务的工作。
1、安装配置docker
[root@k8s-worker1 ~]# tar xvf k8s-node.tar.gz
[root@k8s-worker1 ~]# mv docker.service /usr/lib/systemd/system
[root@k8s-worker1 ~]# mkdir /etc/docker
[root@k8s-worker1 ~]# cp daemon.json /etc/docker
[root@k8s-worker1 ~]# tar xf docker-18.09.6.tgz
[root@k8s-worker1 ~]# mv docker/* /bin/
[root@k8s-worker1 ~]# systemctl start docker
[root@k8s-worker1 ~]# systemctl enable docker
[root@k8s-worker1 ~]# docker info
2、安装kubelet和Kube-proxy服务
1)生成程序目录和管理脚本
[root@k8s-worker1
[root@k8s-worker1 ~]# mv kubelet.service kube-proxy.service /usr/lib/systemd/system/
[root@k8s-worker1 ~]# mv kubernetes /opt/
2)修改配置文件(4个)
[root@k8s-worker1 ~]# vim /opt/kubernetes/cfg/kube-proxy.kubeconfig
修改一行:server: https://192.168.2.151:6443
这里指定的是master的ip地址,并且注意里面指定证书的字段: certificate-authority
[root@k8s-worker1 ~]# vi /opt/kubernetes/cfg/bootstrap.kubeconfig
修改一行: server: https://192.168.2.151:6443
这里指定的是master的ip地址
[root@k8s-worker1 ~]# vim /opt/kubernetes/cfg/kube-proxy-config.yml
修改一行:hostnameOverride: k8s-worker1
这里是指定当前主机的主机名
[root@k8s-worker1 ~]# vim /opt/kubernetes/cfg/kubelet.conf
修改一行:--hostname-override=k8s-worker1
这里是指定当前主机的主机名
3)从master节点复制证书到worker节点
[root@k8s-master1 ~]# cd /root/TLS/k8s/
[root@k8s-master1 k8s]# scp ca.pem kube-proxy.pem kube-proxy-key.pem root@k8s-worker1:/opt/kubernetes/ssl/
4)启动kubelet和kube-proxy服务
[root@k8s-worker1 ~]# systemctl start kube-proxy
[root@k8s-worker1 ~]# systemctl start kubelet
[root@k8s-worker1 ~]# systemctl enable kubelet
[root@k8s-worker1 ~]# systemctl enable kube-proxy
[root@k8s-worker1 ~]# tail -f /opt/kubernetes/logs/kubelet.INFO
如果看到最后一行信息是如下内容,就表示启动服务政策:
No valid private key and/or certificate found, reusing existing private key or creating a new one
5)在master节点为worker节点颁发证书
[root@k8s-master1 k8s]# kubectl get csr
NAME AGE REQUESTOR CONDITION
node-csr-Uu61q1J1nAJ0AprrHc9rcSPVU0qSsD-Z4qDdapDvsWo 6m6s kubelet-bootstrap Pending
[root@k8s-master1 ]# kubectl certificate approve node-csr-Uu61q1J1nAJ0AprrHc9rcSPVU0qSsD-Z4qDdapDvsWo
6)给worker节点颁发证书之后,就可以在master上看到worker节点了
[root@k8s-master1 k8s]# kubectl get node
NAME STATUS ROLES AGE VERSION
k8s-worker1 NotReady <none> 5h13m v1.16.0
k8s-worker1 NotReady <none> 3s v1.16.0
3、安装网络插件
网络插件有flannel、calico等,这是安装的是flannel,相关的介绍参考:https://github.com/flannel-io/flannel?tab=readme-ov-file
1)确认启用CNI
[root@k8s-worker1 ~]# grep "cni" /opt/kubernetes/cfg/kubelet.conf
--network-plugin=cni \
2)安装CNI
[root@k8s-worker1 ~]# mkdir -pv /opt/cni/bin /etc/cni/net.d
[root@k8s-worker1 ~]# tar xf k8s-node.tar.gz
[root@k8s-worker1 ~]# tar xf cni-plugins-linux-amd64-v0.8.2.tgz -C /opt/cni/bin
3)在master上执行yaml脚本,实现在worker节点安装启动网络插件功能
[root@k8s-master1 YAML]# kubectl apply -f kube-flannel.yaml
这是先下载kube-flannel.yaml文件,然后使用kubectl执行yaml文件,也可以参考官网使用命令:
kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
说明:这一步我遇到插件安装不成功的问题,由于篇幅的原因,将在下一篇博客中进行说明。
4、授权apiserver可以访问kubelet
[root@k8s-master1 ~]# kubectl apply -f apiserver-to-kubelet-rbac.yaml
clusterrole.rbac.authorization.k8s.io/system:kube-apiserver-to-kubelet created
clusterrolebinding.rbac.authorization.k8s.io/system:kube-apiserver created
在master上查看节点的信息:
[root@k8s-master1 ~]# kubectl describe node k8s-worker1
八、运行服务
测试启动nginx容器,直接在master上启动nginx镜像:
1、创建deployment,通过deployment来创建和管理nginx容器
[root@k8s-master1 tmp]# kubectl create deployment myweb --image=nginx:1.8
deployment.apps/myweb created
查看一下deployment的状态:
[root@k8s-master1 tmp]# kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
myweb 0/1 1 0 24s
查看pod的状态:
[root@k8s-master1 ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginxdemo-75c5ffcc9c-j6ljb 1/1 Running 0 13d
只在k8s-worker1上启动了Pod。
查看pod运行情况:
[root@k8s-master1 ~]# kubectl describe pod nginxdemo-75c5ffcc9c-j6ljb
可以看到运行在k8s-worker1上面。
2、暴露myweb的端口到物理机
[root@k8s-master1 tmp]# kubectl expose deployment myweb --port=80 --type=NodePort
补充:通过node节点上的docker命令进入到容器中,可以查看端口:
docker exec -it 317fa16d5e58 /bin/bash
[root@k8s-master1 ~]# kubectl expose deployment nginxdemo --port=80 --type=NodePort
端口暴露后,在node节点上可以通过netstat看到暴露后的端口
查看当前将80映射到了哪个端口
[root@k8s-master1 ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 40h
nginxdemo NodePort 10.0.0.169 <none> 80:31451/TCP 5m40s
3、两台worker节点上实际上都已经映射了端口,访问集群任意节点的31451来访问nginx
[root@k8s-master1 ~]# curl http://192.168.2.154:31451
查看deployment的状态:
[root@k8s-master1 ~]# kubectl describe deployment nginxdemo
刚才nginxdemo默认只启动了一个pod,现在再扩展一个出来:
[root@k8s-master1 ~]# kubectl scale --replicas=2 deployment/nginxdemo
deployment.apps/nginxdemo scaled
[root@k8s-master1 ~]#
[root@k8s-master1 ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginxdemo-75c5ffcc9c-65shk 1/1 Running 0 9s
nginxdemo-75c5ffcc9c-j6ljb 1/1 Running 0 61m
[root@k8s-master1 ~]#
[root@k8s-master1 ~]# kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
nginxdemo 2/2 2 2 61m
再查看一下Pod,可以看到两个pod分别在两个不同的worker上运行:
[root@k8s-master1 ~]# kubectl describe pod nginxdemo
九、总结
终于跟着相关的视频及网上的笔记自己也简单的搭建了一遍K8S,主要步骤包括通过Cfssl管理证书、Etcd配置、master配置、worker配置、授权、服务发布等步骤。在这个过程中,又熟悉了K8S的证书管理工具cfssl、K8S网络管理插件flannel等,由于这是K8S搭建的初体验,并且篇幅有限,笔者将在另外的文章中进行说明。