安装k8s 1.15版本
刚好在阿里云买了一台EC2,准备在上面弄一个k8s测试环境,闲来无事顺便记录下过程
之前写过一篇1.12版本安装过程,大家可以参考下:https://www.cnblogs.com/shansongxian/p/9812441.html
此次安装版本为V1.15.x,据说最新1.16很多Helm模板并未更新支持。。
好了,下面是环境说明:
EC2:阿里云香港可用区,2核16G 系统:Ubuntu 18.04 Docker: 19.03.5
k8s工作原理
两个名称概念 Master Node master负责控制管理,node负责运行实际应用 当你需要创建一个容器服务时,首先为你做事情的是 API server,它会把你的 Application 存到 etcd 里,以 API 对象的方式存到 etcd 中去。 而 Kubernetes 中负责编排的是 Controller manager,一堆 controller 通过控制循环在 run。通过这个控制循环来做编排工作,帮你去创建出这些应用所需要的 Pod,注意不是容器,是 Pod。 而一旦一个 Pod 出现之后,Scheduler 会 watch 新 Pod 的变化。如果他发现有一个新的 Pod 出现,Scheduler 会帮你去把所有调度算法都 run 一遍,把 run 到的结果:就是一个 Node 的名字,写在我这个 Pod 对象 NodeName 字段上面,就是一个所谓的 bind 的操作。然后把 bind 的结果写回到 etcd 里去,这就是所谓的 Scheduler 工作过程。所以 Control Panel 它忙活这么一圈下来,最后得到的结果是什么呢?你的一个 Pod 跟一个 Node 绑定(bind)在了一起,就是所谓 Schedule 了。 而 Kubelet 呢?它是运行在所有节点上。Kubelet 会 watch 所有 Pod 对象的变化,当它发现一个 Pod 与一个 Node 绑定在一起的时,并且它又发现这个被绑定的 Node 是它自己,那么 Kubelet 就会帮你去接管接下来的所有事情。 如果你看一下 Kubelet ,看看它在做什么呢?很简单,其实当 Kubelet 拿到这个信息之后,他是去 call 你运行在每个机器上的 Containerd 进程,去 run 这个 Pod 里的每一个容器。 这时候,Containerd 帮你去 call runC 所以最后其实是 runC 帮你去 set up 起来这些 namespace、Cgroup 这些东西,是它去帮你 chroot ,“搭”出来所谓的一个应用和需要的容器。这就是整个 Kubernetes 工作的一个简单原理。
k8s运行环境
先来了解k8s下容器运行的过程 当kubelet想要创建一个容器时,他需要以下几个步骤: 1.Kubelet 通过 CRI 接口(gRPC)调用 dockershim,请求创建一个容器,CRI(容器运行时接口,Container Runtime Interface)。在这一步中 , Kubelet 可以视作一个简单的 CRI Client,而 dockershim 就是接收请求的 Server。目前 dockershim 的代码其实是内嵌在 Kubelet 中的,所以接收调用的就是 Kubelet 进程。 2.dockershim 收到请求后,它会转化成 Docker Daemon 能听懂的请求,发到 Docker Daemon 上,并请求创建一个容器。 3.Docker Daemon 早在 1.12 版本中就已经将针对容器的操作移到另一个守护进程 containerd 中了。因此 Docker Daemon 仍然不能帮人们创建容器,而是需要请求 containerd 创建一个容器。 4.containerd 收到请求后,并不会自己直接去操作容器,而是创建一个叫做 containerd-shim 的进程,让 containerd-shim 去操作容器。这是因为容器进程需要一个父进程来做诸如收集状态、维持 stdin 等 fd 打开工作。假如这个父进程就是 containerd,那每次 containerd 挂掉或升级后,整个宿主机上所有的容器都需要退出,但是引入了 containerd-shim 就规避了这个问题(containerd 和 shim 并不是父子进程关系)。 5. 创建容器是需要做一些设置 namespace 和 Cgroups、挂载 root filesystem 的操作。这些事已经有了公开的规范 OCI(Open Container Initiative,开放容器标准)。它的一个参考实现叫做 runc。containerd-shim 在这一步需要调用 runc 这个命令行工具,来启动容器。 6.runc 启动完容器后,它会直接退出,containerd-shim 则会成为容器进程的父进程,负责收集容器进程的状态,上报给 containerd。并在容器中 pid 为 1 的进程退出后接管容器中的子进程,然后进行清理,确保不会出现僵尸进程。
Docker Runtime运行架构:
更多关于Container Runtime的原理可以阅读这篇文章:https://blog.csdn.net/u011563903/article/details/90743853
简单来说就是除了docker还有很多其它容器引擎服务,如rkt等 ,为了解决不同容器引擎服务被kubelete调用的问题,就产生了CRI这个东东,所有的容器服务只要基于CRI标准就能被kubelet调用。
So,我们这里使用最多的Docker,如果你用的不是Docker则需要另外的CRI shim,例如CRI-O or Containerd等
说这么多其实是对官网的东东进行了一下解释。一开始大家对这些名词可能都是一脸懵逼。 https://kubernetes.io/docs/setup/production-environment/container-runtimes/
1、安装Docker apt-get update && apt-get install \ apt-transport-https ca-certificates curl software-properties-common curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - add-apt-repository \ "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) \ stable" //查看可用的docker版本 apt-cache madison docker-ce //k8s 1.15验证可用的docker版本为18.09 apt-get update && apt-get install \ containerd.io=1.2.10-3 \ docker-ce=5:18.09.9~3-0~ubuntu-$(lsb_release -cs) \ docker-ce-cli=5:18.09.9~3-0~ubuntu-$(lsb_release -cs) //推荐systemd作为Docker cgroup的驱动程序 //https://kubernetes.io/docs/setup/production-environment/container-runtimes/#cgroup-drivers cat > /etc/docker/daemon.json <<EOF { "exec-opts": ["native.cgroupdriver=systemd"], "log-driver": "json-file", "log-opts": { "max-size": "8192m" }, "storage-driver": "overlay2" } EOF mkdir -p /etc/systemd/system/docker.service.d # Restart docker. systemctl daemon-reload systemctl restart docker
调整内核网络参数(可选部分,阿里云主机默认有些参数做了优化)
cat <<EOF > /etc/sysctl.d/99-kubelet-network.conf # Have a larger connection range available net.ipv4.ip_local_port_range=1024 65000 # Reuse closed sockets faster net.ipv4.tcp_tw_reuse=1 net.ipv4.tcp_fin_timeout=15 # The maximum number of "backlogged sockets". Default is 128. net.core.somaxconn=4096 net.core.netdev_max_backlog=4096 # 16MB per socket - which sounds like a lot, # but will virtually never consume that much. net.core.rmem_max=16777216 net.core.wmem_max=16777216 # Various network tunables net.ipv4.tcp_max_syn_backlog=20480 net.ipv4.tcp_max_tw_buckets=400000 net.ipv4.tcp_no_metrics_save=1 net.ipv4.tcp_rmem=4096 87380 16777216 net.ipv4.tcp_syn_retries=2 net.ipv4.tcp_synack_retries=2 net.ipv4.tcp_wmem=4096 65536 16777216 #vm.min_free_kbytes=65536 # Connection tracking to prevent dropped connections (usually issue on LBs) #net.netfilter.nf_conntrack_max=262144 #net.ipv4.netfilter.ip_conntrack_generic_timeout=120 #net.netfilter.nf_conntrack_tcp_timeout_established=86400 # ARP cache settings for a highly loaded docker swarm net.ipv4.neigh.default.gc_thresh1=8096 net.ipv4.neigh.default.gc_thresh2=12288 net.ipv4.neigh.default.gc_thresh3=16384 EOF
禁用swap和安装ipvs
sed
-i
's/.*swap.*/#&/'
/etc/fstab
//默认kube_proxy使用iptables转发,ipvs提供更好的性能和伸缩性,当然这是对大型集群,一般情况下iptables已经够用了 apt install ipvsadm ipset -y cat <<EOF > /etc/sysctl.d/k8s.conf net.ipv4.ip_forward = 1 net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 vm.swappiness = 0 EOF sysctl --system //加载ipvs模块 cat > /tmp/ipvs.modules <<EOF #!/bin/bash ipvs_modules="ip_vs ip_vs_lc ip_vs_wlc ip_vs_rr ip_vs_wrr ip_vs_lblc ip_vs_lblcr ip_vs_dh ip_vs_sh ip_vs_fo ip_vs_nq ip_vs_sed ip_vs_ftp nf_conntrack_ipv4" for kernel_module in \${ipvs_modules}; do /sbin/modinfo -F filename \${kernel_module} > /dev/null 2>&1 if [ $? -eq 0 ]; then /sbin/modprobe \${kernel_module} fi done EOF sh /tmp/ipvs.modules
root@iZj6c35qoc6h285ecl2n4sZ:~# lsmod |grep ip_vs ip_vs_ftp 16384 0 ip_vs_sed 16384 0 ip_vs_nq 16384 0 ip_vs_fo 16384 0 ip_vs_sh 16384 0 ip_vs_dh 16384 0 ip_vs_lblcr 16384 0 ip_vs_lblc 16384 0 ip_vs_wrr 16384 0 ip_vs_rr 16384 0 ip_vs_wlc 16384 0 ip_vs_lc 16384 0 ip_vs 147456 24 ip_vs_wlc,ip_vs_rr,ip_vs_dh,ip_vs_lblcr,ip_vs_sh,ip_vs_fo,ip_vs_nq,ip_vs_lblc,ip_vs_wrr,ip_vs_lc,ip_vs_sed,ip_vs_ftp nf_nat 32768 3 nf_nat_masquerade_ipv4,nf_nat_ipv4,ip_vs_ftp nf_conntrack 131072 8 xt_conntrack,nf_nat_masquerade_ipv4,nf_conntrack_ipv4,nf_nat,ipt_MASQUERADE,nf_nat_ipv4,nf_conntrack_netlink,ip_vs libcrc32c 16384 3 nf_conntrack,nf_nat,ip_vs
重启系统
安装k8s
//直接使用的root账户安装 1、添加k8s apt源 curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add - cat <<EOF | tee /etc/apt/sources.list.d/kubernetes.list deb https://apt.kubernetes.io/ kubernetes-xenial main EOF apt-get update //不指定版本会安装最新稳定版,目前已经是1.17了 //查看包所有版本 apt-get list kubeadm -a apt-get install kubeadm=1.15.7-00 kubelet=1.15.7-00 kubectl=1.15.7-00 -y
到此kubeadm已经安装完成,下面使用kubeadm创建k8s服务
为了更直观知道安装了什么,这里使用config的方式
//打印init默认配置 kubeadm config print init-defaults
apiVersion: kubeadm.k8s.io/v1beta2 bootstrapTokens: - groups: - system:bootstrappers:kubeadm:default-node-token token: abcdef.0123456789abcdef ttl: 24h0m0s usages: - signing - authentication kind: InitConfiguration localAPIEndpoint: advertiseAddress: 1.2.3.4 bindPort: 6443 nodeRegistration: criSocket: /var/run/dockershim.sock name: izj6c35qoc6h285ecl2n4sz taints: - effect: NoSchedule key: node-role.kubernetes.io/master --- apiServer: timeoutForControlPlane: 4m0s apiVersion: kubeadm.k8s.io/v1beta2 certificatesDir: /etc/kubernetes/pki clusterName: kubernetes controllerManager: {} dns: type: CoreDNS etcd: local: dataDir: /var/lib/etcd imageRepository: k8s.gcr.io kind: ClusterConfiguration kubernetesVersion: v1.15.0 networking: dnsDomain: cluster.local serviceSubnet: 10.96.0.0/12 scheduler: {}
根据默认配置和api文档定制化配置文件
https://godoc.org/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2
Example:
apiVersion: kubeadm.k8s.io/v1beta2 kind: InitConfiguration bootstrapTokens: - groups: - system:bootstrappers:kubeadm:default-node-token token: zpyzb4.vnjd9i4j7m5yfut7 #生成随机token: kubeadm token generate ttl: "0" #设置token永不过期,嘿嘿 usages: - signing - authentication localAPIEndpoint: advertiseAddress: 10.10.128.134 #绑定本机api地址,node存在多网口时 bindPort: 6443 nodeRegistration: name: 10.10.128.134 #节点名称,如果是域名需要dns能解析 taints: [] #master不打污点标签 # - effect: NoSchedule # key: node-role.kubernetes.io/master kubeletExtraArgs: cgroup-driver: "systemd" #只在CRI的cgroup驱动程序不是cgroupfs时才需要,docker info查看 node-labels: cluster=stg-k8s-hk,nodegroup=demo,environment=stg,workload=high --- apiVersion: kubeadm.k8s.io/v1beta2 kind: ClusterConfiguration apiServer: extraArgs: address: 0.0.0.0 timeoutForControlPlane: 2m0s controllerManager: extraArgs: bind-address: 0.0.0.0 scheduler: extraArgs: address: 0.0.0.0 clusterName: stg-k8s-hk imageRepository: k8s.gcr.io kubernetesVersion: v1.15.7 # controlPlaneEndpoint: # cluster lb address ro domain networking: dnsDomain: cluster.local serviceSubnet: 10.96.0.0/12 podSubnet: 192.168.0.0/16 --- apiVersion: kubeproxy.config.k8s.io/v1alpha1 kind: KubeProxyConfiguration mode: ipvs --- apiVersion: kubelet.config.k8s.io/v1beta1 kind: KubeletConfiguration healthzBindAddress: 0.0.0.0 imageGCHighThresholdPercent: 79 imageGCLowThresholdPercent: 75 # enforceNodeAllocatable: #默认node可分配资源是pods # - "pods" # - "system-reserved" # systemReserved: #操作系统预留的资源,包含kube预留的资源 # memory: "1.6Gi" #保留10%的内存资源,16Gx10% # systemReservedCgroup: "/sys/fs/cgroup/hugetlb/system.slice/kubelet.service/" cgroupDriver: "systemd" evictionSoft: #kubelet驱逐的阀值,eviction-threshold实际上是对pod limit_resource的补充,可对cpu、memery、disk作限制 memory.available: 15% evictionSoftGracePeriod: #软性驱逐缓冲时间 memory.available: "1m0s" evictionHard: imagefs.available: 15% memory.available: 800Mi nodefs.available: 10% nodefs.inodesFree: 5%
//初始化集群
kubeadm init --config init-config.yaml
//root用户直接添加环境变量
/etc/profile
//kubectl需要读取授权信息访问kubernetes集群
export
KUBECONFIG=
/etc/kubernetes/admin
.conf
到这里就可以测试下集群
kubectl cluster-info
kubectl get cs
//安装网络组件
//这里用calico
根着calico官网撸一遍就行了,懒得写了
https://docs.projectcalico.org/v3.10/getting-started/kubernetes/