Kubernetes组件介绍
Kubernetes Cluster 由 Master 和 Node 组成,节点上运行着若干 Kubernetes 服务。
Master 节点
Master 是 Kubernetes Cluster 的大脑,运行着如下 Daemon 服务:kube-apiserver、kube-scheduler、kube-controller-manager、etcd 和 Pod 网络(例如 flannel)。
API Server(kube-apiserver)
API Server 提供 HTTP/HTTPS RESTful API,即 Kubernetes API。API Server 是 Kubernetes Cluster 的前端接口,各种客户端工具(CLI 或 UI)以及 Kubernetes 其他组件可以通过它管理 Cluster 的各种资源。
Scheduler(kube-scheduler)
Scheduler 负责决定将 Pod 放在哪个 Node 上运行。Scheduler 在调度时会充分考虑 Cluster 的拓扑结构,当前各个节点的负载,以及应用对高可用、性能、数据亲和性的需求。
Controller Manager(kube-controller-manager)
Controller Manager 负责管理 Cluster 各种资源,保证资源处于预期的状态。Controller Manager 由多种 controller 组成,包括 replication controller、endpoints controller、namespace controller、serviceaccounts controller 等。
不同的 controller 管理不同的资源。例如 replication controller 管理 Deployment、StatefulSet、DaemonSet 的生命周期,namespace controller 管理 Namespace 资源。
etcd
etcd 负责保存 Kubernetes Cluster 的配置信息和各种资源的状态信息。当数据发生变化时,etcd 会快速地通知 Kubernetes 相关组件。
Pod 网络
Pod 要能够信相互通,Kubernetes Cluster 必须部署 Pod 网络,flannel 是其中一个可选方案。
以上是 Master 上运行的组件,下一节我们讨论 Node。
上一节我们讨论了 Kubernetes 架构 Master 上运行的服务,本节讨论 Node 节点。
Node 是 Pod 运行的地方,Kubernetes 支持 Docker、rkt 等容器 Runtime。 Node上运行的 Kubernetes 组件有 kubelet、kube-proxy 和 Pod 网络(例如 flannel)。
kubelet
kubelet 是 Node 的 agent(代理),当 Scheduler 确定在某个 Node 上运行 Pod 后,会将 Pod 的具体配置信息(image、volume 等)发送给该节点的 kubelet,kubelet 根据这些信息创建和运行容器,并向 Master 报告运行状态。
kube-proxy
service 在逻辑上代表了后端的多个 Pod,外界通过 service 访问 Pod。service 接收到的请求是如何转发到 Pod 的呢?这就是 kube-proxy 要完成的工作。
每个 Node 都会运行 kube-proxy 服务,它负责将访问 service 的 TCP/UPD 数据流转发到后端的容器。如果有多个副本,kube-proxy 会实现负载均衡。
Pod 网络
Pod 要能够相互通信,Kubernetes Cluster 必须部署 Pod 网络,flannel 是其中一个可选方案。
完整的架构图
结合实验环境,我们得到了如下的架构图:
环境要求
关闭防火墙和selinux
系统 | 内存 | cpu | 主机名 | IP地址 |
---|---|---|---|---|
Centos7.4 | 2G | 2 | master | 192.168.83.3 |
Centos7.4 | 2G | 2 | node2 | 192.168.83.4 |
Centos7.4 | 2G | 2 | node2 | 192.168.83.5 |
一、基础环境准备
配置时间同步(三台操作相同)
[root@localhost ~]# yum install -y chrony ntp
[root@localhost ~]# vim /etc/ntp.conf
将一下四行注释掉:
server 0.centos.pool.ntp.org iburst
server 1.centos.pool.ntp.org iburst
server 2.centos.pool.ntp.org iburst
server 3.centos.pool.ntp.org iburst
添加:
server ntp1.aliyun.com iburst
设置时区为东八区
Linux里面用Asia/Shanghai表示东八区,等价于Windows中的 北京、重庆、香港特别行政区,乌鲁木齐的时区设置
[root@localhost ~]# rm -rf /etc/localtime
[root@localhost ~]# cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
修改完成后查看系统时间是否成功
安装docker版本为18.9.0 (三台操作相同)
添加Centos网络yum源和docker镜像源
[root@localhost ~]# wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
[root@localhost ~]# yum install -y yum-utils device-mapper-persistent-data lvm2
[root@localhost ~]# yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
[root@localhost ~]# yum install -y docker-ce-18.09.0-3.el7 docker-ce-cli-18.09.0-3.el7 containerd.io-1.2.0-3.el7
修改主机名和hosts文件(三台操作相同)
[root@localhost ~]# hostnamectl set-hostname master #两外两台为node01和node02
[root@localhost ~]# bash
[root@master ~]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.83.3 master
192.168.83.4 node01
192.168.83.5 node02
[root@master ~]# scp /etc/hosts root@192.168.83.4:/etc/hosts
root@192.168.83.4's password:
hosts 100% 221 251.3KB/s 00:00
[root@master ~]# scp /etc/hosts root@192.168.83.5:/etc/hosts
root@192.168.83.5's password:
hosts 100% 221 241.3KB/s 00:00
[root@master ~]# ping node01
PING node01 (192.168.83.4) 56(84) bytes of data.
64 bytes from node01 (192.168.83.4): icmp_seq=1 ttl=64 time=0.459 ms
^C
--- node01 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.459/0.459/0.459/0.000 ms
[root@master ~]# ping node02
PING node02 (192.168.83.5) 56(84) bytes of data.
64 bytes from node02 (192.168.83.5): icmp_seq=1 ttl=64 time=0.415 ms
^C
--- node02 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.415/0.415/0.415/0.000 ms
关闭swap(三台操作相同)
安装k8s为什么要关闭swap?
kubernetes的想法是将实例紧密包装到尽可能接近100%。 所有的部署应该与CPU /内存限制固定在一起。 所以如果调度程序发送一个pod到一台机器,它不应该使用交换。 设计者不想交换,因为它会减慢速度。
所以关闭swap主要是为了性能考虑。
[root@master ~]# swapoff -a
取消swap开机自启功能
[root@master ~]# vim /etc/fstab
注释掉swap信息
#/dev/mapper/centos-swap swap swap defaults 0 0
[root@master ~]# free #查看内存使用信息,只要看到swap为0表示关闭
total used free shared buff/cache available
Mem: 2031912 264692 917232 9356 849988 1553136
Swap: 0 0 0
开启iptables桥接功能(三台操作相同)
[root@master ~]# modprobe br_netfilter #加载iptables桥接模块
[root@master ~]# echo "net.bridge.bridge-nf-call-ip6tables = 1" > /etc/sysctl.d/k8s.conf
[root@master ~]# echo "net.bridge.bridge-nf-call-iptables = 1" >> /etc/sysctl.d/k8s.conf
[root@master ~]# sysctl -p /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
设置master免密登录其他节点(master节点操作)
[root@master ~]# ssh-keygen #一路回车
[root@master ~]# ssh-copy-id node01
[root@master ~]# ssh-copy-id node02
测试是否成功
[root@master ~]# ssh node01
Last login: Mon Dec 9 10:07:09 2019 from 192.168.83.1
[root@node01 ~]# exit
登出
Connection to node01 closed.
[root@master ~]# ssh node02
Last login: Mon Dec 9 09:19:42 2019 from 192.168.83.1
[root@node02 ~]# exit
登出
Connection to node02 closed.
二、安装k8s
安装kubeadm1.14.1(master节点操作)
到此基本环境准备完毕,先来master节点上操作
添加k8s镜像源
[root@master ~]# cat /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
[root@master ~]# scp /etc/yum.repos.d/kubernetes.repo root@node01:/etc/yum.repos.d/
[root@master ~]# scp /etc/yum.repos.d/kubernetes.repo root@node02:/etc/yum.repos.d/
[root@master ~]# yum install -y kubelet-1.14.1-0 kubeadm-1.14.1-0 kubectl-1.14.1-0
#设置服务开机自启
[root@mast[root@node01 ~]# er ~]# systemctl enable docker
[root@master ~]# systemctl enable kubelet
#配置docker加速器
[root@master ~]# curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://f1361db2.m.daocloud.io
修改kubelet配置文件,忽略swap信息
[root@master ~]# rpm -ql kubelet
/etc/kubernetes/manifests
/etc/sysconfig/kubelet
/usr/bin/kubelet
/usr/lib/systemd/system/kubelet.service
[root@master ~]# cat /etc/sysconfig/kubelet
KUBELET_EXTRA_ARGS="--fail-swap-on=false"
准备工作做完,可以开始初始化,可是由于国内网络环境限制,我们不能直接从谷歌的镜像站下载镜像,这时,需要我们手工从docker镜像站下载镜像,然后重新命名,这里用脚本来实现。
[root@master ~]# systemctl start docker
[root@master ~]# systemctl status docker
● docker.service - Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
Active: active (running) since 一 2019-12-09 10:48:30 CST; 1min 1s ago
Docs: https://docs.docker.com
Main PID: 39558 (dockerd)
Memory: 55.5M
使用脚本下载指定镜像并且将镜像打标签为kubelet制定镜像名和版本
[root@master ~]# cat images.sh
docker pull mirrorgooglecontainers/kube-apiserver:v1.14.1
docker pull mirrorgooglecontainers/kube-controller-manager:v1.14.1
docker pull mirrorgooglecontainers/kube-scheduler:v1.14.1
docker pull mirrorgooglecontainers/kube-proxy:v1.14.1
docker pull mirrorgooglecontainers/pause:3.1
docker pull mirrorgooglecontainers/etcd:3.3.10
docker pull coredns/coredns:1.3.1
docker tag mirrorgooglecontainers/kube-proxy:v1.14.1 k8s.gcr.io/kube-proxy:v1.14.1
docker tag mirrorgooglecontainers/kube-scheduler:v1.14.1 k8s.gcr.io/kube-scheduler:v1.14.1
docker tag mirrorgooglecontainers/kube-apiserver:v1.14.1 k8s.gcr.io/kube-apiserver:v1.14.1
docker tag mirrorgooglecontainers/kube-controller-manager:v1.14.1 k8s.gcr.io/kube-controller-manager:v1.14.1
docker tag mirrorgooglecontainers/etcd:3.3.10 k8s.gcr.io/etcd:3.3.10
docker tag coredns/coredns:1.3.1 k8s.gcr.io/coredns:1.3.1
docker tag mirrorgooglecontainers/pause:3.1 k8s.gcr.io/pause:3.1
docker rmi mirrorgooglecontainers/kube-apiserver:v1.14.1
docker rmi mirrorgooglecontainers/kube-controller-manager:v1.14.1
docker rmi mirrorgooglecontainers/kube-scheduler:v1.14.1
docker rmi mirrorgooglecontainers/kube-proxy:v1.14.1
docker rmi mirrorgooglecontainers/pause:3.1
docker rmi mirrorgooglecontainers/etcd:3.3.10
docker rmi coredns/coredns:1.3.1
[root@master ~]# sh images.sh
运行完成后查看
[root@master ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
k8s.gcr.io/kube-proxy v1.14.1 20a2d7035165 8 months ago 82.1MB
k8s.gcr.io/kube-apiserver v1.14.1 cfaa4ad74c37 8 months ago 210MB
k8s.gcr.io/kube-controller-manager v1.14.1 efb3887b411d 8 months ago 158MB
k8s.gcr.io/kube-scheduler v1.14.1 8931473d5bdb 8 months ago 81.6MB
k8s.gcr.io/coredns 1.3.1 eb516548c180 10 months ago 40.3MB
k8s.gcr.io/etcd 3.3.10 2c4adeb21b4f 12 months ago 258MB
k8s.gcr.io/pause 3.1 da86e6ba6ca1 23 months ago 742kB
初始化kubeadm
[root@master ~]# kubeadm init --kubernetes-version=v1.14.1 --pod-network-cidr=10.244.0.0/16 --service-cidr=10.96.0.0/12 --ignore-preflight-errors=Swap
#定义POD的网段为: 10.244.0.0/16, api server地址就是master本机IP地址。
执行完成后出现下面信息表示初始化成功
----- 省略部分代码 -----
Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
#### 这里需要注意,要想使用集群需要指定用户运行
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
Then you can join any number of worker nodes by running the following on each as root:
###后续需要用到这条命令在要加入集群的主机上执行下面这条命令
kubeadm join 192.168.83.3:6443 --token v94vpv.obkg7amb2yvso5ne \
--discovery-token-ca-cert-hash sha256:98c04ee14143c8baf1f7cb79d4783f682b4ff18594de86ffa45cb150513a9674
##根据初始化提示制定root用户运行
[root@master ~]# mkdir /root/.kube
[root@master ~]# cp -i /etc/kubernetes/admin.conf /root/.kube/config
[root@master ~]# chown root:root /root/.kube/config
添加网络组件(flannel)
[root@master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master NotReady master 14m v1.14.1
#查看当前master节点状态为notready(未就绪)
之所以是这种状态是因为还缺少一个附件flannel,没有网络各Pod是无法通信的
组件flannel可以通过https://github.com/coreos/flannel中获取
运行flannel组件
[root@master ~]# kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
podsecuritypolicy.policy/psp.flannel.unprivileged created
clusterrole.rbac.authorization.k8s.io/flannel created
clusterrolebinding.rbac.authorization.k8s.io/flannel created
serviceaccount/flannel created
configmap/kube-flannel-cfg created
daemonset.apps/kube-flannel-ds-amd64 created
daemonset.apps/kube-flannel-ds-arm64 created
daemonset.apps/kube-flannel-ds-arm created
daemonset.apps/kube-flannel-ds-ppc64le created
daemonset.apps/kube-flannel-ds-s390x created
查看当前集群状态
[root@master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master Ready master 30m v1.14.1
[root@master ~]# kubectl get cs
NAME STATUS MESSAGE ERROR
scheduler Healthy ok
controller-manager Healthy ok
etcd-0 Healthy {"health":"true"}
### 查看所有名称空间状态,可以看到网络组件运行正常
如果状态为 ContainerCreating表示为正在创建
[root@master ~]# kubectl get pods --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-fb8b8dccf-ltmqz 1/1 Running 0 30m
kube-system coredns-fb8b8dccf-w77pz 1/1 Running 0 30m
kube-system etcd-master 1/1 Running 0 29m
kube-system kube-apiserver-master 1/1 Running 0 30m
kube-system kube-controller-manager-master 1/1 Running 0 29m
kube-system kube-flannel-ds-amd64-gxxq6 1/1 Running 0 11m
kube-system kube-proxy-s5wx5 1/1 Running 0 30m
kube-system kube-scheduler-master 1/1 Running 0 29m
[root@master ~]# kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-fb8b8dccf-ltmqz 1/1 Running 0 31m
coredns-fb8b8dccf-w77pz 1/1 Running 0 31m
etcd-master 1/1 Running 0 30m
kube-apiserver-master 1/1 Running 0 30m
kube-controller-manager-master 1/1 Running 0 30m
kube-flannel-ds-amd64-gxxq6 1/1 Running 0 12m
kube-proxy-s5wx5 1/1 Running 0 31m
kube-scheduler-master 1/1 Running 0 30m
加入集群(node01和node02操作)
[root@node01 ~]# yum -y install kubelet-1.14.1-0 kubeadm-1.14.1-0 kubectl-1.14.1-0
修改kubelet配置文件,忽略swap信息
[root@node01 ~]# echo KUBELET_EXTRA_ARGS="--fail-swap-on=false" > /etc/sysconfig/kubelet
#设置服务开机自启
[root@node01 ~]# systemctl enable docker
[root@node01 ~]# systemctl enable kubelet
#配置docker加速器
[root@node01 ~]# curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://f1361db2.m.daocloud.io
[root@node01 ~]# systemctl restart docker kubelet
#开启路由功能
[root@node01 ~]# echo 1 > /proc/sys/net/ipv4/ip_forward
在加入集群之前,仍需要我们手工下载2个镜像,这样速度更快
[root@node01 ~]# docker pull mirrorgooglecontainers/kube-proxy:v1.14.1
[root@node01 ~]# docker pull mirrorgooglecontainers/pause:3.1
[root@node01 ~]# docker tag mirrorgooglecontainers/kube-proxy:v1.14.1 k8s.gcr.io/kube-proxy:v1.14.1
[root@node01 ~]# docker tag mirrorgooglecontainers/pause:3.1 k8s.gcr.io/pause:3.1
[root@node01 ~]# docker rmi mirrorgooglecontainers/kube-proxy:v1.14.1
[root@node01 ~]# docker rmi mirrorgooglecontainers/pause:3.1
[root@node01 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
k8s.gcr.io/kube-proxy v1.14.1 20a2d7035165 8 months ago 82.1MB
k8s.gcr.io/pause 3.1 da86e6ba6ca1 23 months ago 742kB
[root@node01 ~]# kubeadm join 192.168.83.3:6443 --token v94vpv.obkg7amb2yvso5ne --discovery-token-ca-cert-hash sha256:98c04ee14143c8baf1f7cb79d4783f682b4ff18594de86ffa45cb150513a9674
#执行完成后提示下面信息表示完成
This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.
Run 'kubectl get nodes' on the control-plane to see this node join the cluster.
等待一会去master节点验证。等待的是同步flannel网络。 回到master节点查看
[root@master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master Ready master 6h19m v1.14.1
node01 NotReady <none> 4m57s v1.14.1
node02 NotReady <none> 38s v1.14.1
如果出现NotReady后查看一下集群的状态,这是由于网络原有flannel镜像没有下载下来
[root@master ~]# kubectl get pod --all-namespaces -o wide
kube-system kube-flannel-ds-amd64-djkmk 0/1 Init:ImagePullBackOff 0 29m 192.168.83.5 node02 <none> <none>
kube-system kube-flannel-ds-amd64-whbfv 0/1 Init:ImagePullBackOff 0 33m 192.168.83.4 node01 <none> <none>
解决方式,将flannel镜像copy给node01和node02
[root@master ~]# docker images
quay.io/coreos/flannel v0.11.0-amd64 ff281650a721 10 months ago 52.6MB
[root@master ~]# docker save > flannel.tar quay.io/coreos/flannel:v0.11.0-amd64
[root@master ~]# scp flannel.tar node01:/root/
[root@master ~]# scp flannel.tar node02:/root/
回到node节点(node01和node02操作相同)
[root@node01 ~]# docker load < flannel.tar
[root@node02 ~]# docker load < flannel.tar
重新kubelet服务(三台操作相同)
[root@master ~]# systemctl restart kubelet.service
配置完成后重新回到master查看状态
[root@master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master Ready master 7h3m v1.14.1
node01 Ready <none> 49m v1.14.1
node02 Ready <none> 45m v1.14.1
[root@master ~]#
设置kubectl命令行工具自动补全功能
[root@master ~]# source /usr/share/bash-completion/bash_completion
[root@master ~]# source <(kubectl completion bash)
[root@master ~]# echo "source /usr/share/bash-completion/bash_completion" >> ~/.bashrc
[root@master ~]# echo "source <(kubectl completion bash)" >> ~/.bashrc
[root@master ~]# vim /root/.vimrc
添加:set tabstop=2 #这个输入table键空格个数
[root@master ~]# source .vimrc
[root@master ~]# echo "source .vimrc " >> ~/.bashrc
为了帮助大家更好地理解 Kubernetes 架构,我们部署一个应用来演示各个组件之间是如何协作的。
Kubernetes 部署了 deployment httpd-app,有两个副本 Pod,分别运行在 k8s-node1 和 k8s-node2。
详细讨论整个部署过程。
① kubectl 发送部署请求到 API Server。
② API Server 通知 Controller Manager 创建一个 deployment 资源。
③ Scheduler 执行调度任务,将两个副本 Pod 分发到 k8s-node1 和 k8s-node2。
④ k8s-node1 和 k8s-node2 上的 kubectl 在各自的节点上创建并运行 Pod。
补充两点:
应用的配置和当前状态信息保存在 etcd 中,执行 kubectl get pod 时 API Server 会从 etcd 中读取这些数据。
flannel 会为每个 Pod 都分配 IP。因为没有创建 service,目前 kube-proxy 还没参与进来。
Kubernetes 架构就讨论到这里。从下节开始,我们将通过实践深入学习 Kubernetes 的各种特性。作为容器编排引擎,最重要也是最基本的功能当然是运行容器化应用。下节见。
从本章开始,我们将通过实践深入学习 Kubernetes 的各种特性。作为容器编排引擎,最重要也是最基本的功能当然是运行容器化应用,这就是本章的内容。