k8s学习笔记-Node节点的部署和CoreDNS的部署

kubernetes Node节点包含如下组件
  • flannel
  • docker
  • kubelet
  • kube-proxy
flannel,docker 根据前面的文章自行部署,这里重要介绍kubelet ,kube-proxy 组件

部署kubelet组件 

Master apiserver启用TLS认证后,Node节点kubelet组件想要加入集群,必须使用CA签发的有效证书才能与apiserver通信,当Node节点很多时,签署证书是一件很繁琐的事情,因此有了TLS Bootstrapping机制,kubelet会以一个低权限用户自动向apiserver申请证书,kubelet的证书由apiserver动态签署。

相关文章:

https://mritd.me/2018/01/07/kubernetes-tls-bootstrapping-note/

在 apiserver 配置中指定了一个 token.csv 文件,该文件中是一个预设的用户配置;同时该用户的 Token 和 apiserver 的 CA 证书被写入了 kubelet 所使用的 bootstrap.kubeconfig 配置文件中;这样在首次请求时,kubelet 使用 bootstrap.kubeconfig 中的 apiserver CA 证书来与 apiserver 建立 TLS 通讯,使用 bootstrap.kubeconfig 中的用户 Token 来向 apiserver 声明自己的 RBAC 授权身份,所以,我们需要生成一个kubeconfig 的文件

1.生成kubeconfig文件 

BOOTSTRAP_TOKEN=4274d4ed9dd65b7bddc521916a218f0a #这个内容可以到api指定的token文件中查看
KUBE_APISERVER="https://10.211.55.8:8443" #对外提供的api安全连接端口
# 设置集群参数

cd /etc/ssl/lkubernetes/ 

kubectl config set-cluster kubernetes \
  --certificate-authority=./ca.pem \
  --embed-certs=true \
  --server=${KUBE_APISERVER} \
  --kubeconfig=bootstrap.kubeconfig
# 设置客户端认证参数
kubectl config set-credentials kubelet-bootstrap \
  --token=${BOOTSTRAP_TOKEN} \
  --kubeconfig=bootstrap.kubeconfig
# 设置上下文参数
kubectl config set-context default \
  --cluster=kubernetes \
  --user=kubelet-bootstrap \
  --kubeconfig=bootstrap.kubeconfig
# 设置默认上下文
kubectl config use-context default --kubeconfig=bootstrap.kubeconfig

这里面授权用到的用户是kubelet-bootstap,所以还需要授权因为在有些用户首次启动时,可能与遇到 kubelet 报 401 无权访问 apiserver 的错误;

这是因为在默认情况下,kubelet 通过 bootstrap.kubeconfig 中的预设用户 Token 声明了自己的身份,然后创建 CSR 请求;
但是不要忘记这个用户在我们不处理的情况下他没任何权限的,包括创建 CSR 请求;所以需要如下命令创建一个 ClusterRoleBinding,
将预设用户 kubelet-bootstrap 与内置的 ClusterRole system:node-bootstrapper 绑定到一起,使其能够发起 CSR 请求
kubectl create clusterrolebinding kubelet-bootstrap \
  --clusterrole=system:node-bootstrapper \
  --user=kubelet-bootstrap

这样基本就完成了认证和授权相关的配置,只需要把生成的  bootstrap.kubeconfig 分发到个node节点上

2.增加配置文件 

vim /etc/kubernetes/kubelet  

KUBELET_OPTS="--logtostderr=true \
--v=2 \
--hostname-override=k8s-node1 \
--bootstrap-kubeconfig=/etc/kubernetes/bootstrap.kubeconfig \
--kubeconfig=/etc/kubernetes/kubelet.kubeconfig \
--cert-dir=/etc/kubernetes/ssl \
--pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/google_containers/pause-amd64:3.1 \
--address=10.211.55.12 \
--hostname-override=k8s-node1 \
--rotate-certificates \
--cluster-dns=10.0.0.2 \
--cluster-domain=cluster.local \
--allow-privileged=true \
--fail-swap-on=false"

kubelet --help 可以查看相关参数 

参考文章:

https://www.jianshu.com/p/087895ba7d87

https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/

https://blog.frognew.com/2017/07/kubelet-production-config.html

最好按最新的官网去参考相应的参数 

几个重要参数说明:

ddress:API 
#监听地址,不能为 127.0.0.1,否则 kube-apiserver、heapster 等不能调用 kubelet 的 API;
readOnlyPort=0:
#关闭只读端口(默认 10255)
authentication.anonymous.enabled:
#设置为 false,不允许匿名访问 10250 端口;
authentication.x509.clientCAFile:
#指定签名客户端证书的 CA 证书,开启 HTTP 证书认证;
authentication.webhook.enabled=true:开启 HTTPs bearer token 认证;
#对于未通过 x509 证书和 webhook 认证的请求(kube-apiserver 或其他客户端),将被拒绝,提示 Unauthorized;
authroization.mode=Webhook:
#kubelet 使用 SubjectAccessReview API 查询 kube-apiserver 某 user、group 是否具有操作资源的权限(RBAC);
featureGates.RotateKubeletClientCertificate、featureGates.RotateKubeletServerCertificate:
#自动 rotate 证书,证书的有效期取决于 kube-controller-manager 的 --experimental-cluster-signing-duration 参数;
–cluster-dns 
#指定kubedns的Service IP(可以先分配,后续创建kubedns 服务时指定该IP)
–cluster-domain
#指定域名后缀,与上面的参数同时指定后才会生效;
–hostname-override 
#如果设置了kube-proxy也需要设置该选项,否则会出现找不到Node的情况;

--rotate-certificates

# kubelet 能够自动重载新证书

--cert-dir 
#管理员通过了CSR请求后,kubelet自动在–cert-dir目录创建证书和私钥文件(kubelet-client.crt和kubelet-client.key),然后写入–kubeconfig文件(自动创建 –kubeconfig指定的文件);
----hairpin-mode 
Kubelet 公开了一个 hairpin-mode 标志,如果 pod 试图访问它们自己的 Service VIP,
就可以让 Service 的 endpoints 重新负载到他们自己身上。hairpin-mode 标志必须设置为 hairpin-veth 或者 promiscuous-bridge。默认是promiscuous-bridge
参考文档:http://docs.kubernetes.org.cn/819.html
--pod-infra-container-image
Pod的pause镜像
3.启动脚本的配置

 vim /usr/lib/systemd/system/kubelet.service

[Unit]
Description=Kubernetes Kubelet
After=docker.service
Requires=docker.service
[Service]
EnvironmentFile=/etc/kubernetes/kubelet
ExecStart=/usr/bin/kubelet $KUBELET_OPTS
Restart=on-failure
KillMode=process
[Install]
WantedBy=multi-user.target
systemctl daemon-reload 
systemctl enable kubelet 
systemctl restart kubelet

 查看启动状态和日志,确保正常

4.在Master审批Node加入集群
kubelet 启动后使用 --bootstrap-kubeconfig 向 kube-apiserver 发送 CSR 请求,当这个 CSR 被 approve 后,kube-controller-manager 为 kubelet 创建 TLS 客户端证书、私钥和 --kubeletconfig 文件。
注意:kube-controller-manager 需要配置 --cluster-signing-cert-file 和 --cluster-signing-key-file 参数,才会为 TLS Bootstrap 创建证书和私钥。
节点的 csr 均处于 pending 状态;

此时kubelet的进程有,但是监听端口还未启动,需要进行下面步骤! 

在Master节点查看请求签名的Node: 
[root@k8s-master1 ssl]# kubectl get csr
NAME                                                   AGE     REQUESTOR           CONDITION
node-csr-TvW12euzSdw9mNF4ZSoXrw2tzuEvmuyvErpQX3LbKcA   8m26s   kubelet-bootstrap   Pending

node-csr-AxONIPr10EUclMcM2Ix0MPmjc_nLrlUoxxY6xL-S-ik               23s   kubelet-bootstrap   Pending 

可以手动或自动 approve CSR 请求。推荐使用自动的方式,因为从 v1.8 版本开始,可以自动轮转approve csr 后生成的证书 

1.手动approve csr请求
[root@k8s-master1 ~]# kubectl certificate approve  node-csr-TvW12euzSdw9mNF4ZSoXrw2tzuEvmuyvErpQX3LbKcA
certificatesigningrequest.certificates.k8s.io "node-csr-TvW12euzSdw9mNF4ZSoXrw2tzuEvmuyvErpQX3LbKcA" approved
查看 Approve 结果:
[root@k8s-master1 ~]# kubectl describe csr  node-csr-TvW12euzSdw9mNF4ZSoXrw2tzuEvmuyvErpQX3LbKcA
[root@k8s-master1 ssl]# kubectl get csr
NAME                                                   AGE   REQUESTOR           CONDITION
node-csr-AxONIPr10EUclMcM2Ix0MPmjc_nLrlUoxxY6xL-S-ik   23s   kubelet-bootstrap   Pending
node-csr-TvW12euzSdw9mNF4ZSoXrw2tzuEvmuyvErpQX3LbKcA   12m   kubelet-bootstrap   Approved,Issued
[root@k8s-master1 ssl]# kubectl get nodes
NAME        STATUS       ROLES    AGE     VERSION
k8s-node1   Ready            3d16h   v1.14.3
k8s-node2   NotReady       3d16h   v1.14.3

同理,可以把另一个节点加入

自动方式的配置可以参考下面的文章,这里不在演示了

https://www.orchome.com/1199

https://mritd.me/2018/01/07/kubernetes-tls-bootstrapping-note/  (这个链接没少发了,希望能认真看一次)

在查看服务相关的端口已经启动了

[root@k8s-master2 kubernetes]#  netstat -lnpt|grep kubelet
tcp        0      0 127.0.0.1:10248         0.0.0.0:*               LISTEN      27615/kubelet
tcp        0      0 127.0.0.1:34429         0.0.0.0:*               LISTEN      27615/kubelet
tcp6       0      0 :::10250                :::*                    LISTEN      27615/kubelet
tcp6       0      0 :::10255                :::*                    LISTEN      27615/kubelet

部署kube-proxy组件

kube-proxy 运行在所有node节点上,,它监听 apiserver 中 service 和 Endpoint 的变化情况,创建路由规则来进行服务负载均衡。
本文档讲解部署 kube-proxy 的部署,使用 ipvs 模式。

 1.创建kubeconfig文件

cd /etc/ssl/kubernetes/ 

kubectl config set-cluster kubernetes \
  --certificate-authority=./ca.pem \
  --embed-certs=true \
  --server=${KUBE_APISERVER} \
  --kubeconfig=kube-proxy.kubeconfig

 

kubectl config set-credentials kube-proxy \
  --client-certificate=./kube-proxy.pem \
  --client-key=./kube-proxy-key.pem \
  --embed-certs=true \
  --kubeconfig=kube-proxy.kubeconfig

 

kubectl config set-context default \
  --cluster=kubernetes \
  --user=kube-proxy \
  --kubeconfig=kube-proxy.kubeconfig
kubectl config use-context default --kubeconfig=kube-proxy.kubeconfig

说明: 

指定该证书的 User 为 system:kube-proxy

预定义的clusterrolebinding system:node-proxier 将User system:kube-proxy 与 clusterrole system:node-proxier 绑定,

授予了调用 kube-apiserver Proxy 相关 API 的权限;

2.增加配置文件

vim /etc/kube-prxoy 

KUBE_PROXY_OPTS="--logtostderr=true \
--v=2 \
--hostname-override=k8s-node1 \
--cluster-cidr=10.0.0.0/24 \
--proxy-mode=ipvs \
--kubeconfig=/etc/kubernetes/kube-proxy.kubeconfig"

参考文档:

https://kubernetes.io/docs/reference/command-line-tools-reference/kube-proxy/

参数说明: 

--hostname-override 使用该名字作为标识而不是实际的主机名需要和 kubelet 保持一致

--cluster-cidr 与api-server 保持一样 定义集群IP 范围

--proxy-mode 代理模式,这里用的是ipvs 

--kubeconfig   指定认证和授权的kubeconfig 文件

--healthz-port   配置健康检查服务的端口,0表示禁止 (default 10256)

因为上面的代理模式用到ipvs 所以,我需要确保系统安装了ipvs 相关的服务和模块

yum install ipvsadm ipset -y

modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr modprobe -- ip_vs_sh modprobe -- nf_conntrack_ipv4
yum install ipvsadm -y

cat > /etc/sysconfig/modules/ipvs.modules <<EOF #!/bin/bash modprobe -- ip_vs modprobe -- ip_vs_rr modprobe -- ip_vs_wrr modprobe -- ip_vs_sh modprobe -- nf_conntrack_ipv4 EOF
chmod 755 /etc/sysconfig/modules/ipvs.modules && bash /etc/sysconfig/modules/ipvs.modules && lsmod | grep -e ip_vs -e nf_conntrack_ipv4
[root@k8s-master2 kubernetes]# lsmod |egrep ip_vs
ip_vs_sh               12688  0
ip_vs_wrr              12697  0
ip_vs_rr               12600  4
ip_vs                 145497  10 ip_vs_rr,ip_vs_sh,ip_vs_wrr
nf_conntrack          137239  7 ip_vs,nf_nat,nf_nat_ipv4,xt_conntrack,nf_nat_masquerade_ipv4,nf_conntrack_netlink,nf_conntrack_ipv4
libcrc32c              12644  4 xfs,ip_vs,nf_nat,nf_conntrack

3.配置服务脚本

vim /usr/lib/systemd/system/kube-proxy.service
[Unit]
Description=Kubernetes Proxy
After=network.target
[Service]
EnvironmentFile=-/etc/kubernetes/kube-proxy
ExecStart=/usr/bin/kube-proxy $KUBE_PROXY_OPTS
Restart=on-failure
[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl enable kube-proxy
systemctl restart kube-proxy

查看服务状态和日志

journalctl -u kube-proxy 

[root@k8s-master2 kubernetes]# netstat -nulpt |egrep kube-proxy
tcp        0      0 127.0.0.1:10249         0.0.0.0:*               LISTEN      17047/kube-proxy
tcp6       0      0 :::10256                :::*                    LISTEN      17047/kube-proxy

4. 查看ipvs 规则是否创建

ipvsadm -Ln  

IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.0.0.1:443 rr
  -> 10.211.55.11:6443            Masq    1      1          0
  -> 10.211.55.12:6443            Masq    1      0          0
  -> 10.211.55.13:6443            Masq    1      0          0

可见将所有到 kubernetes cluster ip 443 端口的请求都转发到 kube-apiserver 的 6443 端口。

恭喜!至此node节点部署完成。

这样可以测试一下,因为我们部署完集群,又少一个DNS 来发现服务,所以这里部署一个coreDNS

按官网推荐方式安装,其他组件或者插件都在这个

https://github.com/kubernetes/kubernetes/tree/master/cluster/addons

coredns

https://github.com/kubernetes/kubernetes/tree/master/cluster/addons/dns/coredns

wget https://raw.githubusercontent.com/kubernetes/kubernetes/master/cluster/addons/dns/coredns/coredns.yaml.base

说明一下

镜像可以通过国内阿里云下载,修改标签,或者更换镜像地址都可以,我这里推荐一个下载的地方

docker pull registry.cn-hangzhou.aliyuncs.com/openthings/k8s-gcr-io-coredns:1.3.1

docker tag   registry.cn-hangzhou.aliyuncs.com/openthings/k8s-gcr-io-coredns:1.3.1 k8s.gcr.io/coredns:1.3.1

我这里从dockerhup 下载一个最新的镜像来使用 

 

  containers:
      - name: coredns
        image: coredns/coredns
        imagePullPolicy: IfNotPresent

接下来是需要 修改里面的变量,换成实际的值
kubernetes __PILLAR__DNS__DOMAIN__ in-addr.arpa ip6.arpa  
修改成
kubernetes cluster.local in-addr.arpa ip6.arpa 
memory: __PILLAR__DNS__MEMORY__LIMIT__
按实际情况修改
memory:500M
clusterIP: __PILLAR__DNS__SERVER__
修改成你在kubelet里面定义的DNS 
clusterIP: 10.0.0.2
是deploy 部署,默认是一个POD,所以根据实际情况修改
# replicas: not specified here:   
# 1. In order to make Addon Manager do not reconcile this replicas parameter.  
# 2. Default is 1.   
# 3. Will be tuned in real time if DNS horizontal auto-scaling is turned on. 
replicas: 2
kubectl apply -f coredns.yaml
默认所以的资源都在kube-system名称空间里面,通过yaml 文件也可以看到
[root@k8s-master1 k8s]# kubectl get all -n kube-system
 NAME                           READY   STATUS    RESTARTS   AGE 
pod/coredns-5b8d7c984b-5bvbd   1/1     Running   1            3m 
pod/coredns-5b8d7c984b-hm5q7   1/1     Running   1            3m  
NAME               TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGE 
service/kube-dns   ClusterIP   10.0.0.2             53/UDP,53/TCP,9153/TCP    3m  
NAME                      READY   UP-TO-DATE   AVAILABLE   AGE 
deployment.apps/coredns   2/2     2            2           5h53m 
NAME                                 DESIRED   CURRENT   READY   AGE 
replicaset.apps/coredns-5b8d7c984b   2         2         2       3m
可以看到cluster-ip 是10.0.0.2 满足之前的需求
测试一下:
下面编写了一个nginx web 测试案例  

vim nginx-web.yaml 

apiVersion: v1
kind: Service
metadata:
  name: nginx-web
  labels:
    tier: frontend
spec:
  type: NodePort
  selector:
    tier: frontend
  ports:
  - name: http
    port: 80
    targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
     tier: frontend
  template:
    metadata:
      labels:
        tier: frontend
    spec:
     containers:
     - name: nginx
       image: nginx
       ports:
       - name: http
         containerPort: 80
[root@k8s-master1 k8s]# kubectl get svc |egrep nginx 
nginx-web    NodePort    10.0.0.15            80:18401/TCP   11m
[root@k8s-master1 k8s]# kubectl get pod -o wide
NAME                     READY   STATUS    RESTARTS   AGE     IP            NODE        NOMINATED NODE   READINESS GATES
nginx-8448bb446d-2q55w   1/1     Running   0          8m30s   172.17.69.3   k8s-node2              
nginx-8448bb446d-h2km5   1/1     Running   0          8m30s   172.17.51.3   k8s-node1              
nginx-8448bb446d-vwkg8   1/1     Running   0          8m30s   172.17.51.4   k8s-node1              
[root@k8s-master1 k8s]# kubectl get ep nginx-web
NAME        ENDPOINTS                                      AGE
nginx-web   172.17.51.3:80,172.17.51.4:80,172.17.69.3:80   12m

测试

[root@k8s-master1 ~]# curl 10.0.0.15
Welcome to nginx!

Welcome to nginx!

If you see this page, the nginx web server is successfully installed and

working. Further configuration is required.

For online documentation and support please refer to

Commercial support is available at

Thank you for using nginx.

我们这里借助DNS 来实现名称访问

启动一个测试pod

[root@k8s-master1 k8s]# kubectl run cirror-$RANDOM --rm -it --image=cirros -- /bin/sh
kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
If you don't see a command prompt, try pressing enter.
/ # cat /etc/resolv.conf
nameserver 10.0.0.2
search default.svc.cluster.local. svc.cluster.local. cluster.local. localdomain
options ndots:5
/ # nslookup nginx-web

 

Server:    10.0.0.2
Address 1: 10.0.0.2 kube-dns.kube-system.svc.cluster.local
Name:      nginx-web
Address 1: 10.0.0.15 nginx-web.default.svc.cluster.local

成功解析出IP 

/ # curl nginx-web
Welcome to nginx!

Welcome to nginx!

If you see this page, the nginx web server is successfully installed and

working. Further configuration is required.

For online documentation and support please refer to

Commercial support is available at

Thank you for using nginx.

说明各Pod可以通过DNS 来解析服务名称了

总结一下:

如果在kubelet 里面配置 --anonymous-auth=false然后在master 完成csr以后报错

failed to run Kubelet: No authentication method configured  

具体需要理解kubelet 的认证和授权:

kubelet 与 kube-apiserver 之间的通信是双向的, kubelet 既需要访问 kube-apiserver 获取分配到自己节点上的 pod 信息, kube-apiserver 也需要主动访问 kubelet 拉取日志, 状态, 监控数据等信息, 所以对两个组件来说, 认证是双向的, kube-apiserver 需要持有 kubelet 的客户端证书, 以完成 kubelet 对自己身份的校验; kubelet 也需要持有 kube-apiserver 的客户端证书, 完成 kube-apiserver 对自己身份的认证.

默认情况下, 对 kubelet 的 https 请求, 如果没有被配置的其他身份验证拒绝的话, 则被视为匿名请求, 并为这个请求赋予system:anonymous用户名和system:unauthenticated用户组

如需要禁用匿名访问, 可以在启动 kubelet Daemon 时加入--anonymous-auth=false配置, 当有匿名访问时, 将回复401 Unauthorized响应未认证的请求

  • kubelet 启动时添加--client-ca-file参数, 并指定签发客户端证书的 ca 根证书所在路径
  • kube-apiserver 启动时添加--kubelet-client-certificate--kubelet-client-key参数, 并分别为其指定由 kubelet ca 根证书签发的客户端证书和秘钥

任何被成功认证的请求(包括匿名请求)都将被授权. 默认的授权模式为AlwaysAllow, 即允许所有类型的请求

  • 匿名访问启用时, 应限制其调用 kubelet API 的能力
  • 客户端证书身份认证启用时, 只允许配置 CA 签名的客户端证书使用 kubelet API
  • 确保authorization.k8s.io/v1beta1该 API Group 在 kube-apiserver 中是被启动的状态
  • 在 kubelet Daemon 启动参数中, 确保配置了--authorization-mode=Webhook--kubeconfig两个参数

kubelet 在接收到每个请求后, 会向指定的 kube-apiserver 发起 SubjectAccessReview API 的请求, 来确定该请求是否被允许

相关文档:

https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-authentication-authorization/ 

https://jimmysong.io/kubernetes-handbook/guide/kubelet-authentication-authorization.html

https://www.orchome.com/1199 

转载于:https://www.cnblogs.com/centos-python/articles/11049426.html

你可能感兴趣的:(运维,开发工具,网络)