二进制安装k8s

二进制安装k8s

Kubernetes概述

1.Kubernetes是什么

•Kubernetes是Google在2014年开源的一个容器集群管理系统,Kubernetes简称K8S。
•K8S用于容器化应用程序的部署,扩展和管理。
•K8S提供了容器编排,资源调度,弹性伸缩,部署管理,服务发现等一系列功能。
•Kubernetes目标是让部署容器化应用简单高效。
官方网站:http://www.kubernetes.io

K8S知识图谱

在这里插入图片描述

2.Kubernetes特性

  • 自我修复
    在节点故障时重新启动失败的容器,替换和重新部署,保证预期的副本数量;杀死健康检查失败的容器,并且在未准备好之前不会处理客户端请求,确保线上服务不中断。
  • 弹性伸缩
    使用命令、UI或者基于CPU使用情况自动快速扩容和缩容应用程序实例,保证应用业务高峰并发时的高可用性;业务低峰时回收资源,以最小成本运行服务。
  • 自动部署和回滚
    K8S采用滚动更新策略更新应用,一次更新一个Pod,而不是同时删除所有Pod,如果更新过程中出现问题,将回滚更改,确保升级不受影响业务。
  • 服务发现和负载均衡
    K8S为多个容器提供一个统一访问入口(内部IP地址和一个DNS名称),并且负载均衡关联的所有容器,使得用户无需考虑容器IP问题。
  • 机密和配置管理
    管理机密数据和应用程序配置,而不需要把敏感数据暴露在镜像里,提高敏感数据安全性。并可以将一些常用的配置存储在K8S中,方便应用程序使用。
  • 存储编排
    挂载外部存储系统,无论是来自本地存储,公有云(如AWS),还是网络存储(如NFS、GlusterFS、Ceph)都作为集群资源的一部分使用,极大提高存储使用灵活性。
  • 批处理
    提供一次性任务,定时任务;满足批量数据处理和分析的场景。

3.Kubernetes集群架构与组件

在这里插入图片描述
![在这里插入图片描述](https://img-blog.csdnimg.cn/a130eebf82b14c54863c67cdf240b508.png

- Master组件

  • kube-apiserver

    Kubernetes API,集群的统一入口,各组件协调者,以RESTful API提供接口 服务,所有对象资源的增删改查和监听操作都交给APIServer处理后再提交给
    Etcd存储。

  • kube-controller-manager

    处理集群中常规后台任务,一个资源对应一个控制器,而ControllerManager 就是负责管理这些控制器的。

  • kube-scheduler

    根据调度算法为新创建的Pod选择一个Node节点,可以任意部署,可以部署在 同一个节点上,也可以部署在不同的节点上。

  • etcd

    分布式键值存储系统。用于保存集群状态数据,比如Pod、Service等对象信息。

- Node组件

  • kubelet

    kubelet是Master在Node节点上的Agent,管理本机运行容器的生命周期,比如创 建容器、Pod挂载数据卷、下载secret、获取容器和节点状态等工作。kubelet将每 个Pod转换成一组容器。

  • kube-proxy

    在Node节点上实现Pod网络代理,维护网络规则和四层负载均衡工作。

  • docker或rocket

    容器引擎,运行容器。

4.Kubernetes核心概念-

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wIdH0Rqw-1659059271641)(./assets/1572835346237.png)]

Pod

  • 最小部署单元
    一组容器的集合
    一个Pod中的容器共享网络命名空间
    Pod是短暂的

Controllers

  • ReplicaSet : 确保预期的Pod副本数量

  • Deployment : 无状态应用部署

  • StatefulSet : 有状态应用部署

  • DaemonSet : 确保所有Node运行同一个Pod

  • Job : 一次性任务

  • Cronjob : 定时任务

    更高级层次对象,部署和管理Pod

Service

  • 防止Pod失联
  • 定义一组Pod的访问策略

Label

  • 标签,附加到某个资源上,用于关联对象、查询和筛选

Namespaces

  • 命名空间,将对象逻辑上隔离

Annotations

  • 注释

01.系统初始化和全局变量

集群机器

Node名称 ip_addr keepalived HAPROXY MASTER WORKER
keepalive-1 192.168.3.141 yes yes yes
keepalive-2 192.168.3.142 yes yes yes
keepalive-3 192.168.3.143 yes yes yes
k8master-1 192.168.3.144 yes
k8master-2 192.168.3.145 yes
k8master-3 192.168.3.146 yes
k8worker-1 192.168.3.147 yes
k8worker-2 192.168.3.148 yes
VIP 192.168.3.140
Note
Master-包括: kube-apiserver kube-controller-manager kube-scheduler etcd
Worker-包括: kubelet kube-proxy flannel

注意:

  1. 本文档中的 etcd 集群、master 节点使用k8master这三台机器;
  2. 需要在所有机器上执行本文档的初始化命令;
  3. 需要使用 root 账号执行这些命令;
  4. 如果没有特殊指明,本文档的所有操作均在 k8master-1 节点上执行,然后远程分发文件和执行命令;

主机名

设置永久主机名称,然后重新登录:

hostnamectl set-hostname k8master-1 # 将 k8master-1 替换为当前主机名
  • 设置的主机名保存在 /etc/hosts 文件中;

如果 DNS 不支持解析主机名称,则需要修改每台机器的 /etc/hosts 文件,添加主机名和 IP 的对应关系:

cat >> /etc/hosts <<EOF
192.168.3.140 vip
192.168.3.141 ka-1
192.168.3.142 ka-2
192.168.3.143 ka-3
192.168.3.144 k8master-1
192.168.3.145 k8master-2
192.168.3.146 k8master-3
192.168.3.147 k8worker-1
192.168.3.148 k8worker-2
EOF

添加 docker 账户

在每台机器上添加 docker 账户:

useradd -m docker

无密码 ssh 登录其它节点

设置 k8master-1 的 root 账户可以无密码登录所有节点

ssh-keygen -t rsa
ssh-copy-id root@k8master-1
ssh-copy-id root@k8master-2
ssh-copy-id root@k8master-3
ssh-copy-id root@ka-1
ssh-copy-id root@ka-2
ssh-copy-id root@ka-3
ssh-copy-id root@k8worker-1
ssh-copy-id root@k8worker-2
ssh-copy-id root@k8worker-3

更新 PATH 变量

将可执行文件目录添加到 PATH 环境变量中:

echo 'PATH=/app/k8s/bin:$PATH' >>/root/.bashrc
source /root/.bashrc

安装依赖包

在每台机器上安装依赖包:

CentOS:

yum -y install bridge-utils chrony ipvsadm ipset sysstat conntrack libseccomp wget tcpdump screen vim nfs-utils bind-utils wget socat telnet sshpass net-tools sysstat lrzsz yum-utils device-mapper-persistent-data lvm2 tree nc lsof strace nmon iptraf iftop rpcbind mlocate ipvsadm
  • ipvs 依赖 ipset;
  • ntp 保证各机器系统时间同步;

关闭防火墙

在每台机器上关闭防火墙,清理防火墙规则,设置默认转发策略:

systemctl stop firewalld
setenforce 0
sed -i 's/^SELINUX=.\*/SELINUX=disabled/' /etc/selinux/config

关闭 swap 分区

如果开启了 swap 分区,kubelet 会启动失败(可以通过将参数 --fail-swap-on 设置为 false 来忽略 swap on),故需要在每台机器上关闭 swap 分区。同时注释 /etc/fstab 中相应的条目,防止开机自动挂载 swap 分区:

swapoff -a
sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab 

关闭 SELinux

关闭 SELinux,否则后续 K8S 挂载目录时可能报错 Permission denied

setenforce 0
sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config

优化资源配置

cat >> /etc/security/limits.conf <<EOF
* soft noproc 65535
* hard noproc 65535
* soft nofile 65535
* hard nofile 65535
* soft memlock unlimited
* hard memlock unlimited
EOF

加载内核模块

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  # 4.19内核已改名为nf_conntrack,这里报错可忽略
modprobe -- overlay
modprobe -- br_netfilter
EOF

chmod 755 /etc/sysconfig/modules/ipvs.modules 
bash /etc/sysconfig/modules/ipvs.modules 
lsmod | grep -e ip_vs -e nf_conntrack_ipv4

优化内核参数

cat > kubernetes.conf <<EOF
net.bridge.bridge-nf-call-iptables=1
net.bridge.bridge-nf-call-ip6tables=1
net.ipv4.ip_forward=1
net.ipv4.tcp_tw_recycle=0
vm.swappiness=0 # 禁止使用 swap 空间,只有当系统 OOM 时才允许使用它
vm.overcommit_memory=1 # 不检查物理内存是否够用
vm.panic_on_oom=0 # 开启 OOM
fs.inotify.max_user_instances=8192
fs.inotify.max_user_watches=1048576
fs.file-max=52706963
fs.nr_open=52706963
net.ipv6.conf.all.disable_ipv6=1
net.netfilter.nf_conntrack_max=2310720
EOF
cp kubernetes.conf  /etc/sysctl.d/kubernetes.conf
sysctl -p /etc/sysctl.d/kubernetes.conf
  • 必须关闭 tcp_tw_recycle,否则和 NAT 冲突,会导致服务不通;
  • 关闭 IPV6,防止触发 docker BUG;

设置系统时区

# 调整系统 TimeZone
timedatectl set-timezone Asia/Shanghai

# 将当前的 UTC 时间写入硬件时钟
timedatectl set-local-rtc 0

# 重启依赖于系统时间的服务
systemctl restart rsyslog 
systemctl restart crond

关闭无关的服务

systemctl stop postfix && systemctl disable postfix

设置 rsyslogd 和 systemd journald

systemd 的 journald 是 Centos 7 缺省的日志记录工具,它记录了所有系统、内核、Service Unit 的日志。

相比 systemd,journald 记录的日志有如下优势:

  1. 可以记录到内存或文件系统;(默认记录到内存,对应的位置为 /run/log/jounal);
  2. 可以限制占用的磁盘空间、保证磁盘剩余空间;
  3. 可以限制日志文件大小、保存的时间;

journald 默认将日志转发给 rsyslog,这会导致日志写了多份,/var/log/messages 中包含了太多无关日志,不方便后续查看,同时也影响系统性能。

mkdir /var/log/journal # 持久化保存日志的目录
mkdir /etc/systemd/journald.conf.d
cat > /etc/systemd/journald.conf.d/99-prophet.conf <<EOF
[Journal]
# 持久化保存到磁盘
Storage=persistent

# 压缩历史日志
Compress=yes

SyncIntervalSec=5m
RateLimitInterval=30s
RateLimitBurst=1000

# 最大占用空间 10G
SystemMaxUse=10G

# 单日志文件最大 200M
SystemMaxFileSize=200M

# 日志保存时间 2 周
MaxRetentionSec=2week

# 不将日志转发到 syslog
ForwardToSyslog=no
EOF
systemctl restart systemd-journald

master-1 创建环境变量文件

cat /app/k8s/bin/environment.sh << EOF
#!/bin/bash

# 生成 EncryptionConfig 所需的加密 key
export ENCRYPTION_KEY=$(head -c 32 /dev/urandom | base64)

# 集群各机器 IP 数组
export NODE_IPS=(192.168.3.141 192.168.3.142 192.168.3.143 192.168.3.144 192.168.3.145 192.168.3.146 192.168.3.147 192.168.3.148)

# 集群各 IP 对应的主机名数组
export NODE_NAMES=(ka-1 ka-2 ka-3 k8master-1 k8master-2 k8master-3 k8worker-1 k8worker-2)

# etcd 集群服务地址列表
export ETCD_ENDPOINTS="https://192.168.3.144:2379,https://192.168.3.145:2379,https://192.168.3.146:2379"

# etcd 集群间通信的 IP 和端口
export ETCD_NODES="k8master-1=https://192.168.3.144:2380,k8master-2=https://192.168.3.145:2380,k8master-3=https://192.168.3.146:2380"

#etcd IP
export ETCD_IPS=(192.168.3.144 192.168.3.145 192.168.3.146)
export API_IPS=(192.168.3.144 192.168.3.145 192.168.3.146)
export CTL_IPS=(192.168.3.144 192.168.3.145 192.168.3.146)
export WORK_IPS=(192.168.3.141 192.168.3.142 192.168.3.143 192.168.3.147 192.168.3.148)
export KA_IPS=(192.168.3.141 192.168.3.142 192.168.3.143)
export VIP_IP="192.168.3.140"


# kube-apiserver 的反向代理(kube-nginx)地址端口
export KUBE_APISERVER="https://192.168.3.140:8443"

# 节点间互联网络接口名称
export IFACE="ens192"

# etcd 数据目录
export ETCD_DATA_DIR="/app/k8s/etcd/data"

# etcd WAL 目录,建议是 SSD 磁盘分区,或者和 ETCD_DATA_DIR 不同的磁盘分区
export ETCD_WAL_DIR="/app/k8s/etcd/wal"

# k8s 各组件数据目录
export K8S_DIR="/app/k8s/k8s"

# docker 数据目录
export DOCKER_DIR="/app/k8s/docker"

## 以下参数一般不需要修改

# TLS Bootstrapping 使用的 Token,可以使用命令 head -c 16 /dev/urandom | od -An -t x | tr -d ' ' 生成
BOOTSTRAP_TOKEN="41f7e4ba8b7be874fcff18bf5cf41a7c"

# 最好使用 当前未用的网段 来定义服务网段和 Pod 网段

# 服务网段,部署前路由不可达,部署后集群内路由可达(kube-proxy 保证)
SERVICE_CIDR="10.254.0.0/16"

# Pod 网段,建议 /16 段地址,部署前路由不可达,部署后集群内路由可达(flanneld 保证)
CLUSTER_CIDR="172.1.0.0/16"

# 服务端口范围 (NodePort Range)
export NODE_PORT_RANGE="30000-32767"

# flanneld 网络配置前缀
export FLANNEL_ETCD_PREFIX="/kubernetes/network"

# kubernetes 服务 IP (一般是 SERVICE_CIDR 中第一个IP)
export CLUSTER_KUBERNETES_SVC_IP="10.254.0.1"

# 集群 DNS 服务 IP (从 SERVICE_CIDR 中预分配)
export CLUSTER_DNS_SVC_IP="10.254.0.2"

# 集群 DNS 域名(末尾不带点号)
export CLUSTER_DNS_DOMAIN="cluster.local"

# 将二进制目录 /app/k8s/bin 加到 PATH 中
export PATH=/app/k8s/bin:$PATH
EOF

创建相关目录

创建目录:

mkdir -p  /app/k8s/{
   bin,work} /etc/{
   kubernetes,etcd}/cert

升级内核

升级内核,详见:
https://gitee.com/lenovux/k8s/blob/master/B.centos7%E5%86%85%E6%A0%B8%E5%8D%87%E7%BA%A7.md

分发集群配置参数脚本

后续使用的环境变量都定义在文件 A.实用脚本.md 的[environment.sh]中,请根据自己的机器、网络情况修改。然后,把它拷贝到所有节点的 /app/k8s/bin 目录。
tags: TLS, CA, x509

02.创建 CA 证书和秘钥

为确保安全,kubernetes 系统各组件需要使用 x509 证书对通信进行加密和认证。

CA (Certificate Authority) 是自签名的根证书,用来签名后续创建的其它证书。

本文档使用 CloudFlare 的 PKI 工具集 cfssl 创建所有证书。

注意:如果没有特殊指明,本文档的所有操作均在k8master-1 节点上执行,然后远程分发文件和执行命令。

安装 cfssl 工具集

sudo mkdir -p /app/k8s/cert && cd /app/k8s
wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
mv cfssl_linux-amd64 /app/k8s/bin/cfssl

wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
mv cfssljson_linux-amd64 /app/k8s/bin/cfssljson

wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
mv cfssl-certinfo_linux-amd64 /app/k8s/bin/cfssl-certinfo

chmod +x /app/k8s/bin/*
export PATH=/app/k8s/bin:$PATH

创建根证书 (CA)

CA 证书是集群所有节点共享的,只需要创建一个 CA 证书,后续创建的所有证书都由它签名。

创建配置文件

CA 配置文件用于配置根证书的使用场景 (profile) 和具体参数 (usage,过期时间、服务端认证、客户端认证、加密等),后续在签名其它证书时需要指定特定场景。

cd /app/k8s/work
cat > ca-config.json <<EOF
{
  "signing": {
    "default": {
      "expiry": "87600h"
    },
    "profiles": {
      "kubernetes": {
        "usages": [
            "signing",
            "key encipherment",
            "server auth",
            "client auth"
        ],
        "expiry": "87600h"
      }
    }
  }
}
EOF
  • signing:表示该证书可用于签名其它证书,生成的 ca.pem 证书中 CA=TRUE
  • server auth:表示 client 可以用该该证书对 server 提供的证书进行验证;
  • client auth:表示 server 可以用该该证书对 client 提供的证书进行验证;

创建证书签名请求文件

cd /app/k8s/work
cat > ca-csr.json <<EOF
{
  "CN": "kubernetes",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "hangzhou",
      "L": "hangzhou",
      "O": "k8s",
      "OU": "CMCC"
    }
  ],
  "ca": {
    "expiry": "876000h"
 }
}
EOF
  • CN:Common Name,kube-apiserver 从证书中提取该字段作为请求的用户名 (User Name),浏览器使用该字段验证网站是否合法;
  • O:Organization,kube-apiserver 从证书中提取该字段作为请求用户所属的组 (Group)
  • kube-apiserver 将提取的 User、Group 作为 RBAC 授权的用户标识;

生成 CA 证书和私钥

cd /app/k8s/work
cfssl gencert -initca ca-csr.json | cfssljson -bare ca
ls ca*

签发etcd证书

1.创建证书请求文件

cd /app/k8s/work
cat > etcd-csr.json <<EOF
{
  "CN": "etcd",
  "hosts": [
    "127.0.0.1",
    "192.168.3.144",
    "192.168.3.145",
    "192.168.3.146",
    "192.168.3.140"
  ],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "hangzhou",
      "L": "hangzhou",
      "O": "k8s",
      "OU": "CMCC"
    }
  ]
}
EOF

2.签发证书

cd /app/k8s/work
cfssl gencert -ca=/app/k8s/work/ca.pem \
    -ca-key=/app/k8s/work/ca-key.pem \
    -config=/app/k8s/work/ca-config.json \
    -profile=kubernetes etcd-csr.json | cfssljson -bare etcd
ls etcd*pem

签发apiserver证书

1.创建证书请求文件

source /app/k8s/bin/environment.sh
cat > kubernetes-csr.json <<EOF
{
  "CN": "kubernetes",
  "hosts": [
    "127.0.0.1",
    "192.168.3.144",
    "192.168.3.145",
    "192.168.3.146",
    "192.168.3.140",
    "${CLUSTER_KUBERNETES_SVC_IP}",
    "kubernetes",
    "kubernetes.default",
    "kubernetes.default.svc",
    "kubernetes.default.svc.cluster",
    "kubernetes.default.svc.cluster.local."
  ],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "zhejiang",
      "L": "hangzhou",
      "O": "k8s",
      "OU": "CMCC"
    }
  ]
}
EOF

2.签发证书

cfssl gencert -ca=/app/k8s/work/ca.pem \
  -ca-key=/app/k8s/work/ca-key.pem \
  -config=/app/k8s/work/ca-config.json \
  -profile=kubernetes kubernetes-csr.json | cfssljson -bare kubernetes
ls kubernetes*pem

签发controller-manager证书

1.创建证书请求配置文件

cd /app/k8s/work
cat > kube-controller-manager-csr.json <<EOF
{
    "CN": "system:kube-controller-manager",
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "hosts": [
      "127.0.0.1",
      "192.168.3.144",
      "192.168.3.145",
      "192.168.3.146",
      "192.168.3.140"
    ],
    "names": [
      {
        "C": "CN",
        "ST": "zhejiang",
        "L": "hangzhou",
        "O": "system:kube-controller-manager",
        "OU": "CMCC"
      }
    ]
}
EOF

2.签发证书

cd /app/k8s/work
cfssl gencert -ca=/app/k8s/work/ca.pem \
  -ca-key=/app/k8s/work/ca-key.pem \
  -config=/app/k8s/work/ca-config.json \
  -profile=kubernetes kube-controller-manager-csr.json | cfssljson -bare kube-controller-manager
ls kube-controller-manager*pem

签发scheduler证书

1.创建证书请求配置文件

cd /app/k8s/work
cat > kube-scheduler-csr.json <<EOF
{
    "CN": "system:kube-scheduler",
    "hosts": [
      "127.0.0.1",
      "192.168.3.146",
      "192.168.3.145",
      "192.168.3.144",
      "192.168.3.140"
    ],
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
      {
        "C": "CN",
        "ST": "zhejiang",
        "L": "hangzhou",
        "O": "system:kube-scheduler",
        "OU": "CMCC"
      }
    ]
}
EOF

2.签发证书

cd /app/k8s/work
cfssl gencert -ca=/app/k8s/work/ca.pem \
  -ca-key=/app/k8s/work/ca-key.pem \
  -config=/app/k8s/work/ca-config.json \
  -profile=kubernetes kube-scheduler-csr.json | cfssljson -bare kube-scheduler
ls kube-scheduler*pem

签发kubectl(admin)证书

1.创建证书请求配置文件

cd /app/k8s/work
cat > admin-csr.json <<EOF
{
  "CN": "admin",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "system:masters",
      "OU": "4Paradigm"
    }
  ]
}
EOF

这里绑定的不是User(用户),而是Group(组),使用O指定组。如果部署完后你想查看,可以通过如下命令:k get ClusterRolebinding cluster-admin -o yaml

2.签发证书

cd /app/k8s/work
cfssl gencert -ca=/app/k8s/work/ca.pem \
  -ca-key=/app/k8s/work/ca-key.pem \
  -config=/app/k8s/work/ca-config.json \
  -profile=kubernetes admin-csr.json | cfssljson -bare admin
ls admin*

签发kube-proxy证书

1.创建证书请求配置文件

cd /app/k8s/work
cat > kube-proxy-csr.json <<EOF
{
  "CN": "system:kube-proxy",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "zhejiang",
      "L": "hangzhou",
      "O": "k8s",
      "OU": "CMCC"
    }
  ]
}
EOF

2.签发证书

cd /app/k8s/work
cfssl gencert -ca=/app/k8s/work/ca.pem \
  -ca-key=/app/k8s/work/ca-key.pem \
  -config=/app/k8s/work/ca-config.json \
  -profile=kubernetes  kube-proxy-csr.json | cfssljson -bare kube-proxy
ls kube-proxy*

配置flannel证书

1.创建证书请求配置文件

cd /app/k8s/work
cat > flanneld-csr.json <<EOF
{
  "CN": "flanneld",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "zhejiang",
      "L": "hangzhou",
      "O": "k8s",
      "OU": "CMCC"
    }
  ]
}
EOF

2.签发证书

cfssl gencert -ca=/app/k8s/work/ca.pem \
  -ca-key=/app/k8s/work/ca-key.pem \
  -config=/app/k8s/work/ca-config.json \
  -profile=kubernetes flanneld-csr.json | cfssljson -bare flanneld
ls flanneld*pem

分发证书文件

将生成的 CA 证书、秘钥文件、配置文件拷贝到所有节点/etc/kubernetes/cert 目录下:

cd /app/k8s/work
source /app/k8s/bin/environment.sh
for node_ip in ${NODE_IPS[@]}
  do
    echo ">>> ${node_ip}"
    ssh root@${node_ip} "mkdir -p /etc/kubernetes/cert"
    scp flanneld*pem ca-config.json root@${node_ip}:/etc/flanneld/cert
  done

参考

  1. 各种 CA 证书类型:https://github.com/kubernetes-incubator/apiserver-builder/blob/master/docs/concepts/auth.md

tags: kubectl

03.部署 kubectl 命令行工具

本文档介绍安装和配置 kubernetes 集群的命令行管理工具 kubectl 的步骤。

kubectl 默认从 ~/.kube/config 文件读取 kube-apiserver 地址和认证信息,如果没有配置,执行 kubectl 命令时可能会出错:

$ kubectl get pods
The connection to the server localhost:8080 was refused - did you specify the right host or port?

注意:

  1. 如果没有特殊指明,本文档的所有操作均在 k8master-1 节点上执行,然后远程分发文件和执行命令;
  2. 本文档只需要部署一次,生成的 kubeconfig 文件是通用的,可以拷贝到需要执行 kubectl 命令的机器,重命名为 ~/.kube/config

下载和分发 kubectl 二进制文件

下载和解压:

cd /app/k8s/work
curl -LO https://dl.k8s.io/release/v1.22.0/bin/linux/amd64/kubectl

分发到所有使用 kubectl 的节点:

cd /app/k8s/work
source /app/k8s/bin/environment.sh
for node_ip in ${NODE_IPS[@]}
  do
    echo ">>> ${node_ip}"
    scp kubectl root@${node_ip}:/app/k8s/bin/
    ssh root@${node_ip} "chmod +x /app/k8s/bin/*"
  done

创建 kubeconfig 文件

kubeconfig 为 kubectl 的配置文件,包含访问 apiserver 的所有信息,如 apiserver 地址、CA 证书和自身使用的证书;

cd /app/k8s/work
source /app/k8s/bin/environment.sh

# 设置集群参数
kubectl config set-cluster kubernetes \
  --certificate-authority=/app/k8s/work/ca.pem \
  --embed-certs=true \
  --server=${KUBE_APISERVER} \
  --kubeconfig=kubectl.kubeconfig

# 设置客户端认证参数
kubectl config set-credentials admin \
  --client-certificate=/app/k8s/work/admin.pem \
  --client-key=/app/k8s/work/admin-key.pem \
  --embed-certs=true \
  --kubeconfig=kubectl.kubeconfig

# 设置上下文参数
kubectl config set-context kubernetes \
  --cluster=kubernetes \
  --user=admin \
  --kubeconfig=kubectl.kubeconfig

# 设置默认上下文
kubectl config use-context kubernetes --kubeconfig=kubectl.kubeconfig
  • --certificate-authority:验证 kube-apiserver 证书的根证书;
  • --client-certificate--client-key:刚生成的 admin 证书和私钥,连接 kube-apiserver 时使用;
  • --embed-certs=true:将 ca.pem 和 admin.pem 证书内容嵌入到生成的 kubectl.kubeconfig 文件中(不加时,写入的是证书文件路径,后续拷贝 kubeconfig 到其它机器时,还需要单独拷贝证书文件,不方便。);

分发 kubeconfig 文件

分发到所有使用 kubectl 命令的节点:

cd /app/k8s/work
source /app/k8s/bin/environment.sh
for node_ip in ${NODE_IPS[@]}
  do
    echo ">>> ${node_ip}"
    ssh root@${node_ip} "mkdir -p ~/.kube"
    scp kubectl.kubeconfig root@${node_ip}:~/.kube/config
  done
  • 保存的文件名为 ``;

使用kubecoler增强显示

wget https://github.com//dty1er/kubecolor/releases/download/v0.0.20/kubecolor_0.0.20_Linux_x86_64.tar.gz
tar -zvxf kubecolor_0.0.20_Linux_x86_64.tar.gz 
cp kubecolor /app/k8s/bin/
chmod +x /app/k8s/bin/*
echo 'command -v kubecolor >/dev/null 2>&1 && alias k="kubecolor"' >> ~/.bashrc
echo 'complete -o default -F __start_kubectl k' >> ~/.bashrc
source ~/.bashrc
kubecolor get pods

tags: etcd

04.部署 etcd 集群

etcd 是基于 Raft 的分布式 key-value 存储系统,由 CoreOS 开发,常用于服务发现、共享配置以及并发控制(如 leader 选举、分布式锁等)。kubernetes 使用 etcd 存储所有运行数据。

本文档介绍部署一个三节点高可用 etcd 集群的步骤:

  • 下载和分发 etcd 二进制文件;
  • 创建 etcd 集群各节点的 x509 证书,用于加密客户端(如 etcdctl) 与 etcd 集群、etcd 集群之间的数据流;
  • 创建 etcd 的 systemd unit 文件,配置服务参数;
  • 检查集群工作状态;

etcd 集群各节点的名称和 IP 如下:

  • 192.168.3.144 k8master-1
  • 192.168.3.145 k8master-2
  • 192.168.3.146 k8master-3

注意:如果没有特殊指明,本文档的所有操作均在 k8master-1 节点上执行,然后远程分发文件和执行命令。

下载和分发 etcd 二进制文件

到 etcd 的 release 页面 下载最新版本的发布包:

cd /app/k8s/work
wget https://github.com/etcd-io/etcd/releases/download/v3.5.0/etcd-v3.5.0-linux-amd64.tar.gz
tar -zxvf etcd-v3.5.0-linux-amd64.tar.gz

分发二进制文件到集群所有节点:

cd /app/k8s/work
source /app/k8s/bin/environment.sh
for node_ip in ${ETCD_IPS[@]}
  do
    echo ">>> ${node_ip}"
    scp etcd-v3.5.0-linux-amd64/etcd* root@${node_ip}:/app/k8s/bin
    ssh root@${node_ip} "chmod +x /app/k8s/bin/*"
  done

分发生成的证书和私钥到各 etcd 节点:

cd /app/k8s/work
source /app/k8s/bin/environment.sh
for node_ip in ${ETCD_IPS[@]}
  do
    echo ">>> ${node_ip}"
    ssh root@${node_ip} "mkdir -p /etc/etcd/cert"
    scp etcd*.pem root@${node_ip}:/etc/etcd/cert/
  done

创建 etcd 的 systemd unit 模板文件

cd /app/k8s/work
source /app/k8s/bin/environment.sh
cat > etcd.service.template <<EOF
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
Documentation=https://github.com/coreos

[Service]
Type=notify
WorkingDirectory=${ETCD_DATA_DIR}
ExecStart=/app/k8s/bin/etcd \\
  --data-dir=${ETCD_DATA_DIR} \\
  --wal-dir=${ETCD_WAL_DIR} \\
  --name=##NODE_NAME## \\
  --cert-file=/etc/etcd/cert/etcd.pem \\
  --key-file=/etc/etcd/cert/etcd-key.pem \\
  --trusted-ca-file=/etc/kubernetes/cert/ca.pem \\
  --peer-cert-file=/etc/etcd/cert/etcd.pem \\
  --peer-key-file=/etc/etcd/cert/etcd-key.pem \\
  --peer-trusted-ca-file=/etc/kubernetes/cert/ca.pem \\
  --peer-client-cert-auth \\
  --client-cert-auth \\
  --listen-peer-urls=https://##NODE_IP##:2380 \\
  --initial-advertise-peer-urls=https://##NODE_IP##:2380 \\
  --listen-client-urls=https://##NODE_IP##:2379,http://127.0.0.1:2379 \\
  --advertise-client-urls=https://##NODE_IP##:2379 \\
  --initial-cluster-token=etcd-cluster-0 \\
  --initial-cluster=${ETCD_NODES} \\
  --initial-cluster-state=new \\
  --auto-compaction-mode=periodic \\
  --auto-compaction-retention=1 \\
  --max-request-bytes=33554432 \\
  --quota-backend-bytes=6442450944 \\
  --heartbeat-interval=250 \\
  --election-timeout=2000 \\
  --enable-v2=true
Restart=on-failure
RestartSec=5
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
EOF
  • WorkingDirectory--data-dir:指定工作目录和数据目录为 ${ETCD_DATA_DIR},需在启动服务前创建这个目录;
  • --wal-dir:指定 wal 目录,为了提高性能,一般使用 SSD 或者和 --data-dir 不同的磁盘;
  • --name:指定节点名称,当 --initial-cluster-state 值为 new 时,--name 的参数值必须位于 --initial-cluster 列表中;
  • --cert-file--key-file:etcd server 与 client 通信时使用的证书和私钥;
  • --trusted-ca-file:签名 client 证书的 CA 证书,用于验证 client 证书;
  • --peer-cert-file--peer-key-file:etcd 与 peer 通信使用的证书和私钥;
  • --peer-trusted-ca-file:签名 peer 证书的 CA 证书,用于验证 peer 证书;

或者这个配置:

[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
Documentation=https://github.com/coreos

[Service]
Type=notify
WorkingDirectory=/app/k8s/etcd/data
ExecStart=/app/k8s/bin/etcd \
  --data-dir=/app/k8s/etcd/data \
  --wal-dir=/app/k8s/etcd/wal \
  --name=k8master-1 \
  --cert-file=/etc/etcd/cert/etcd.pem \
  --key-file=/etc/etcd/cert/etcd-key.pem \
  --trusted-ca-file=/etc/kubernetes/cert/ca.pem \
  --peer-cert-file=/etc/etcd/cert/etcd.pem \
  --peer-key-file=/etc/etcd/cert/etcd-key.pem \
  --peer-trusted-ca-file=/etc/kubernetes/cert/ca.pem \
  --peer-client-cert-auth \
  --client-cert-auth \
  --listen-peer-urls=https://192.168.3.144:2380 \
  --initial-advertise-peer-urls=https://192.168.3.144:2380 \
  --listen-client-urls=https://192.168.3.144:2379,http://127.0.0.1:2379 \
  --advertise-client-urls=https://192.168.3.144:2379 \
  --initial-cluster-token=etcd-cluster-0 \
  --initial-cluster=k8master-1=https://192.168.3.144:2380,k8master-2=https://192.168.3.145:2380,k8master-3=https://192.168.3.146:2380
  --initial-cluster-state=new \
  --auto-compaction-mode=periodic \
  --auto-compaction-retention=1 \
  --max-request-bytes=33554432 \
  --quota-backend-bytes=6442450944 \
  --heartbeat-interval=250 \
  --election-timeout=2000
  --enable-v2=true

Restart=on-failure
RestartSec=5
LimitNOFILE=65536

为各节点创建和分发 etcd systemd unit 文件

替换模板文件中的变量,为各节点创建 systemd unit 文件:

cd /app/k8s/work
source /app/k8s/bin/environment.sh
for (( i=0; i < 9; i++ ))
  do
    sed -e "s/##NODE_NAME##/${NODE_NAMES[i]}/" -e "s/##NODE_IP##/${NODE_IPS[i]}/" etcd.service.template > etcd-${NODE_IPS[i]}.service 
  done
ls *.service
  • NODE_NAMES 和 NODE_IPS 为相同长度的 bash 数组,分别为节点名称和对应的 IP;

分发生成的 systemd unit 文件:

cd /app/k8s/work
source /app/k8s/bin/environment.sh
for node_ip in ${ETCD_IPS[@]}
  do
    echo ">>> ${node_ip}"
    scp etcd-${node_ip}.service root@${node_ip}:/etc/systemd/system/etcd.service
  done
  • 文件重命名为 etcd.service;

启动 etcd 服务

cd /app/k8s/work
source /app/k8s/bin/environment.sh
for node_ip in ${ETCD_IPS[@]}
  do
    echo ">>> ${node_ip}"
    ssh root@${node_ip} "mkdir -p ${ETCD_DATA_DIR} ${ETCD_WAL_DIR}"
    ssh root@${node_ip} "systemctl daemon-reload && systemctl enable etcd && systemctl restart etcd " &
  done
  • 必须先创建 etcd 数据目录和工作目录;
  • etcd 进程首次启动时会等待其它节点的 etcd 加入集群,命令 systemctl start etcd 会卡住一段时间,为正常现象;

检查启动结果

cd /app/k8s/work
source /app/k8s/bin/environment.sh
for node_ip in ${ETCD_IPS[@]}
  do
    echo ">>> ${node_ip}"
    ssh root@${node_ip} "systemctl status etcd|grep Active"
  done

确保状态为 active (running),否则查看日志,确认原因:

journalctl -u etcd

验证服务状态

部署完 etcd 集群后,在任一 etcd 节点上执行如下命令:

cd /app/k8s/work
source /app/k8s/bin/environment.sh
for node_ip in ${ETCD_IPS[@]}
  do
    echo ">>> ${node_ip}"
    ETCDCTL_API=3 /app/k8s/bin/etcdctl \
    --endpoints=https://${node_ip}:2379 \
    --cacert=/etc/kubernetes/cert/ca.pem \
    --cert=/etc/etcd/cert/etcd.pem \
    --key=/etc/etcd/cert/etcd-key.pem endpoint health
  done

预期输出:

>>> 172.27.137.240
https://172.27.137.240:2379 is healthy: successfully committed proposal: took = 2.756451ms
>>> 172.27.137.239
https://172.27.137.239:2379 is healthy: successfully committed proposal: took = 2.025018ms
>>> 172.27.137.238
https://172.27.137.238:2379 is healthy: successfully committed proposal: took = 2.335097ms

输出均为 healthy 时表示集群服务正常。

查看当前的 leader

source /app/k8s/bin/environment.sh
ETCDCTL_API=3 /app/k8s/bin/etcdctl \
  -w table --cacert=/etc/kubernetes/cert/ca.pem \
  --cert=/etc/etcd/cert/etcd.pem \
  --key=/etc/etcd/cert/etcd-key.pem \
  --endpoints=${ETCD_ENDPOINTS} endpoint status 

输出:

+----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
|          ENDPOINT          |        ID        | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS |
+----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| https://192.168.3.144:2379 | 4c3f96aeaf516ead |   3.5.0 |   29 kB |     false |      false |        16 |         44 |                 44 |        |
| https://192.168.3.145:2379 | 166a0a39c02deebc |   3.5.0 |   20 kB |     false |      false |        16 |         44 |                 44 |        |
| https://192.168.3.146:2379 | 4591e7e99dfd9a5e |   3.5.0 |   20 kB |      true |      false |        16 |         44 |                 44 |        |
+----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+

  • 可见,当前的 leader 为 172.27.137.239。

trouble-shooting

如果出现 IS LEADER 2个true,检查日志发现:
request cluster ID mismatch

需要删除:

/app/k8s/etcd/work/*
/app/k8s/etcd/wal/*

再重启服务

tags: flanneld

05.部署 flannel 网络

kubernetes 要求集群内各节点(包括 master 节点)能通过 Pod 网段互联互通。flannel 使用 vxlan 技术为各节点创建一个可以互通的 Pod 网络,使用的端口为 UDP 8472(需要开放该端口,如公有云 AWS 等)。

flanneld 第一次启动时,从 etcd 获取配置的 Pod 网段信息,为本节点分配一个未使用的地址段,然后创建 flannedl.1 网络接口(也可能是其它名称,如 flannel1 等)。

flannel 将分配给自己的 Pod 网段信息写入 /app/flannel/docker 文件,docker 后续使用这个文件中的环境变量设置 docker0 网桥,从而从这个地址段为本节点的所有 Pod 容器分配 IP。

注意:如果没有特殊指明,本文档的所有操作均在 k8master-1 节点上执行,然后远程分发文件和执行命令。

下载和分发 flanneld & CNI插件 二进制文件

从 flannel 的 release 页面 下载最新版本的安装包:

cd /app/k8s/work
mkdir flannel
wget https://github.com/coreos/flannel/releases/download/v0.14.0/flannel-v0.14.0-linux-amd64.tar.gz
tar -xzvf flannel-v0.14.0-linux-amd64.tar.gz -C flannel
cd /app/k8s/work
mkdir cni
wget https://github.com/containernetworking/plugins/releases/download/v0.9.1/cni-plugins-linux-amd64-v0.9.1.tgz
tar -xvf cni-plugins-linux-amd64-v0.9.1.tgz -C cni

分发flanneld二进制文件到集群所有节点:

cd /app/k8s/work
source /app/k8s/bin/environment.sh
for node_ip 
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值