说明:由于最近计划开展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

基础网络安全-K8S部署初体验_k8s

cfssl print-defaults csr > csr.json

基础网络安全-K8S部署初体验_k8s_02

 2、通过csr请求文件生成CA证书及CA私钥:

cfssl gencert -initca csr.json | cfssljson -bare ca

基础网络安全-K8S部署初体验_docker_03

此时生成了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

基础网络安全-K8S部署初体验_docker_04

可以看到生成了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如下:

基础网络安全-K8S部署初体验_k8s_05

Worker2如下:

基础网络安全-K8S部署初体验_docker_06

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

基础网络安全-K8S部署初体验_docker_07

五、为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的配置文件

基础网络安全-K8S部署初体验_docker_08

注意配置/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

基础网络安全-K8S部署初体验_k8s_09

2)可以查看集群信息:

kubectl get cs

基础网络安全-K8S部署初体验_docker_10

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部署初体验_docker_11

可以看到运行在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看到暴露后的端口

基础网络安全-K8S部署初体验_docker_12

        查看当前将80映射到了哪个端口

基础网络安全-K8S部署初体验_k8s_13

[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

基础网络安全-K8S部署初体验_k8s_14

刚才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

基础网络安全-K8S部署初体验_docker_15

再查看一下Pod,可以看到两个pod分别在两个不同的worker上运行:

[root@k8s-master1 ~]# kubectl describe pod nginxdemo

 九、总结

终于跟着相关的视频及网上的笔记自己也简单的搭建了一遍K8S,主要步骤包括通过Cfssl管理证书、Etcd配置、master配置、worker配置、授权、服务发布等步骤。在这个过程中,又熟悉了K8S的证书管理工具cfssl、K8S网络管理插件flannel等,由于这是K8S搭建的初体验,并且篇幅有限,笔者将在另外的文章中进行说明。