k3s集群搭建与Rancher部署
1.环境准备
1.1 初始化机器 安装所需要的包
curl http://pigx.vip/os7init.sh | sh -s k3s-master
curl http://pigx.vip/os7init.sh | sh -s k3s-node1
curl http://pigx.vip/os7init.sh | sh -s k3s-node2
文件 os7init.sh
#!/bin/bash
# init centos7 ./centos7-init.sh 主机名
# 检查是否为root用户,脚本必须在root权限下运行
if [[ "$(whoami)" != "root" ]]; then
echo "please run this script as root !" >&2
exit 1
fi
echo -e "\033[31m the script only Support CentOS_7 x86_64 \033[0m"
echo -e "\033[31m system initialization script, Please Seriously. press ctrl+C to cancel \033[0m"
# 检查是否为64位系统,这个脚本只支持64位脚本
platform=`uname -i`
if [ $platform != "x86_64" ];then
echo "this script is only for 64bit Operating System !"
exit 1
fi
if [ "$1" == "" ];then
echo "The host name is empty."
exit 1
else
hostnamectl --static set-hostname $1
hostnamectl set-hostname $1
fi
cat << EOF
+---------------------------------------+
| your system is CentOS 7 x86_64 |
| start optimizing |
+---------------------------------------+
EOF
sleep 1
# 安装必要支持工具及软件工具
yum_update(){
yum update -y
yum install -y nmap unzip wget vim lsof xz net-tools iptables-services ntpdate ntp-doc psmisc
}
# 设置时间同步 set time
zone_time(){
timedatectl set-timezone Asia/Shanghai
/usr/sbin/ntpdate 0.cn.pool.ntp.org > /dev/null 2>&1
/usr/sbin/hwclock --systohc
/usr/sbin/hwclock -w
cat > /var/spool/cron/root << EOF
10 0 * * * /usr/sbin/ntpdate 0.cn.pool.ntp.org > /dev/null 2>&1
* * * * */1 /usr/sbin/hwclock -w > /dev/null 2>&1
EOF
chmod 600 /var/spool/cron/root
/sbin/service crond restart
sleep 1
}
# 修改文件打开数 set the file limit
limits_config(){
cat > /etc/rc.d/rc.local << EOF
#!/bin/bash
touch /var/lock/subsys/local
ulimit -SHn 1024000
EOF
sed -i "/^ulimit -SHn.*/d" /etc/rc.d/rc.local
echo "ulimit -SHn 1024000" >> /etc/rc.d/rc.local
sed -i "/^ulimit -s.*/d" /etc/profile
sed -i "/^ulimit -c.*/d" /etc/profile
sed -i "/^ulimit -SHn.*/d" /etc/profile
cat >> /etc/profile << EOF
ulimit -c unlimited
ulimit -s unlimited
ulimit -SHn 1024000
EOF
source /etc/profile
ulimit -a
cat /etc/profile | grep ulimit
if [ ! -f "/etc/security/limits.conf.bak" ]; then
cp /etc/security/limits.conf /etc/security/limits.conf.bak
fi
cat > /etc/security/limits.conf << EOF
* soft nofile 1024000
* hard nofile 1024000
* soft nproc 1024000
* hard nproc 1024000
hive - nofile 1024000
hive - nproc 1024000
EOF
if [ ! -f "/etc/security/limits.d/20-nproc.conf.bak" ]; then
cp /etc/security/limits.d/20-nproc.conf /etc/security/limits.d/20-nproc.conf.bak
fi
cat > /etc/security/limits.d/20-nproc.conf << EOF
* soft nproc 409600
root soft nproc unlimited
EOF
sleep 1
}
# 优化内核参数 tune kernel parametres
sysctl_config(){
if [ ! -f "/etc/sysctl.conf.bak" ]; then
cp /etc/sysctl.conf /etc/sysctl.conf.bak
fi
#add
cat > /etc/sysctl.conf << EOF
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv4.tcp_syn_retries = 1
net.ipv4.tcp_synack_retries = 1
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.tcp_keepalive_intvl =15
net.ipv4.tcp_retries1 = 3
net.ipv4.tcp_retries2 = 5
net.ipv4.tcp_fin_timeout = 10
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_max_tw_buckets = 60000
net.ipv4.tcp_max_orphans = 32768
net.ipv4.tcp_max_syn_backlog = 16384
net.ipv4.tcp_mem = 94500000 915000000 927000000
net.ipv4.tcp_wmem = 4096 16384 13107200
net.ipv4.tcp_rmem = 4096 87380 17476000
net.ipv4.ip_local_port_range = 1024 65000
net.ipv4.ip_forward = 1
net.ipv4.route.gc_timeout = 100
net.core.somaxconn = 32768
net.core.netdev_max_backlog = 32768
net.nf_conntrack_max = 6553500
net.netfilter.nf_conntrack_max = 6553500
net.netfilter.nf_conntrack_tcp_timeout_established = 180
vm.overcommit_memory = 1
vm.swappiness = 1
fs.file-max = 1024000
EOF
#reload sysctl
/sbin/sysctl -p
sleep 1
}
# 设置UTF-8 LANG="zh_CN.UTF-8"
LANG_config(){
echo "LANG=\"en_US.UTF-8\"">/etc/locale.conf
source /etc/locale.conf
}
#关闭SELINUX disable selinux
selinux_config(){
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
setenforce 0
sleep 1
}
#日志处理
log_config(){
setenforce 0
systemctl start systemd-journald
systemctl status systemd-journald
}
# 关闭防火墙
firewalld_config(){
/usr/bin/systemctl stop firewalld.service
/usr/bin/systemctl disable firewalld.service
}
# SSH配置优化 set sshd_config
sshd_config(){
if [ ! -f "/etc/ssh/sshd_config.bak" ]; then
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
fi
cat >/etc/ssh/sshd_config<<EOF
Port 22
AddressFamily inet
ListenAddress 0.0.0.0
Protocol 2
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
SyslogFacility AUTHPRIV
PermitRootLogin yes
MaxAuthTries 6
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
PasswordAuthentication yes
ChallengeResponseAuthentication no
UsePAM yes
UseDNS no
X11Forwarding yes
UsePrivilegeSeparation sandbox
AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE
AcceptEnv XMODIFIERS
Subsystem sftp /usr/libexec/openssh/sftp-server
EOF
/sbin/service sshd restart
}
# 关闭ipv6 disable the ipv6
ipv6_config(){
echo "NETWORKING_IPV6=no">/etc/sysconfig/network
echo 1 > /proc/sys/net/ipv6/conf/all/disable_ipv6
echo 1 > /proc/sys/net/ipv6/conf/default/disable_ipv6
echo "127.0.0.1 localhost localhost.localdomain">/etc/hosts
#sed -i 's/IPV6INIT=yes/IPV6INIT=no/g' /etc/sysconfig/network-scripts/ifcfg-enp0s8
for line in $(ls -lh /etc/sysconfig/network-scripts/ifcfg-* | awk -F '[ ]+' '{print $9}')
do
if [ -f $line ]
then
sed -i 's/IPV6INIT=yes/IPV6INIT=no/g' $line
echo $i
fi
done
}
# 设置历史命令记录格式 history
history_config(){
export HISTFILESIZE=10000000
export HISTSIZE=1000000
export PROMPT_COMMAND="history -a"
export HISTTIMEFORMAT="%Y-%m-%d_%H:%M:%S "
##export HISTTIMEFORMAT="{\"TIME\":\"%F %T\",\"HOSTNAME\":\"\$HOSTNAME\",\"LI\":\"\$(who -u am i 2>/dev/null| awk '{print \$NF}'|sed -e 's/[()]//g')\",\"LU\":\"\$(who am i|awk '{print \$1}')\",\"NU\":\"\${USER}\",\"CMD\":\""
cat >>/etc/bashrc<<EOF
alias vi='vim'
HISTDIR='/var/log/command.log'
if [ ! -f \$HISTDIR ];then
touch \$HISTDIR
chmod 666 \$HISTDIR
fi
export HISTTIMEFORMAT="{\"TIME\":\"%F %T\",\"IP\":\"\$(ip a | grep -E '192.168|172' | head -1 | awk '{print \$2}' | cut -d/ -f1)\",\"LI\":\"\$(who -u am i 2>/dev/null| awk '{print \$NF}'|sed -e 's/[()]//g')\",\"LU\":\"\$(who am i|awk '{print \$1}')\",\"NU\":\"\${USER}\",\"CMD\":\""
export PROMPT_COMMAND='history 1|tail -1|sed "s/^[ ]\+[0-9]\+ //"|sed "s/$/\"}/">> /var/log/command.log'
EOF
source /etc/bashrc
}
# 服务优化设置
service_config(){
/usr/bin/systemctl enable NetworkManager-wait-online.service
/usr/bin/systemctl start NetworkManager-wait-online.service
/usr/bin/systemctl stop postfix.service
/usr/bin/systemctl disable postfix.service
chmod +x /etc/rc.local
chmod +x /etc/rc.d/rc.local
#ls -l /etc/rc.d/rc.local
}
# VIM设置
vim_config(){
cat > /root/.vimrc << EOF
set history=1000
EOF
#autocmd InsertLeave * se cul
#autocmd InsertLeave * se nocul
#set nu
#set bs=2
#syntax on
#set laststatus=2
#set tabstop=4
#set go=
#set ruler
#set showcmd
#set cmdheight=1
#hi CursorLine cterm=NONE ctermbg=blue ctermfg=white guibg=blue guifg=white
#set hls
#set cursorline
#set ignorecase
#set hlsearch
#set incsearch
#set helplang=cn
}
# done
done_ok(){
touch /var/log/init-ok
cat << EOF
+-------------------------------------------------+
| optimizer is done |
| it's recommond to restart this server ! |
| Please Reboot system |
+-------------------------------------------------+
EOF
}
# main
main(){
yum_update
zone_time
limits_config
sysctl_config
LANG_config
selinux_config
log_config
firewalld_config
sshd_config
ipv6_config
history_config
service_config
vim_config
done_ok
}
main
1.2 然后重启
reboot
1.3 安装docker(所有机器)
curl http://pigx.vip/docker_install.sh | sh
文件 docker_install.sh
#!/bin/sh
set -e
# 在线安装脚本
# k3s 不建议安装swap 系统内存小的时候没有swap会卡死
if [ ! -f "/var/swap" ];then
echo "create swap"
dd if=/dev/zero of=/var/swap bs=1024 count=8192000
mkswap /var/swap
mkswap -f /var/swap
swapon /var/swap
echo "/var/swap swap swap defaults 0 0" >> /etc/fstab
fi
# 判断是否安装 docker
if [ `command -v docker` ];then
echo 'docker has installed'
else
echo 'install docker'
curl https://download.daocloud.io/docker/linux/centos/docker-ce.repo -o /etc/yum.repos.d/docker-ce.repo
yum -y install https://download.daocloud.io/docker/linux/centos/7/x86_64/stable/Packages/containerd.io-1.2.6-3.3.el7.x86_64.rpm
curl -fsSL https://get.daocloud.io/docker | bash -s docker --mirror Aliyun
# centos7 的内核经过 k3s 检查都有这个问题
grubby --args="user_namespace.enable=1" --update-kernel="$(grubby --default-kernel)"
fi
# 添加加速源
sudo mkdir -p /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirror":[
"https://registry.cn-hangzhou.aliyuncs.com"
],
"features":{
"buildkit":true
},
"insecure-registries":[
"172.19.1.217",
"registry.cn-hangzhou.aliyuncs.com"
],
"debug":true,
"experimental":true,
"builder":{
"gc":{
"enabled":true,
"defaultKeepStorage":"20GB"
}
}
}
EOF
# 启动
sudo systemctl daemon-reload
sudo systemctl restart docker
sudo systemctl enable docker
echo 'finish'
1.4 关闭防火墙(所有机器)
systemctl stop firewalld
systemctl disable firewalld
setenforce 0
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
1.5 修改主机名
hostnamectl set-hostname k3s-master
hostnamectl set-hostname k3s-node1
hostnamectl set-hostname k3s-node2
1.6 添加hosts
cat >> /etc/hosts <<EOF
172.19.1.224 k3s-master
172.19.1.217 k3s-node2
172.19.1.200 k3s-node1
EOF
2.部署k3s
# master 节点
export INSTALL_K3S_VERSION=v1.22.7+k3s1
export INSTALL_K3S_EXEC="--service-node-port-range=1-65000"
# containerd 安装
curl -sfL http://rancher-mirror.cnrancher.com/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn sh -s - server
# docker 安装
curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn sh -s - --docker
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
kubectl get pods --all-namespaces
helm ls --all-namespaces
echo "export KUBECONFIG=/etc/rancher/k3s/k3s.yaml" >> ~/.bash_profile
source ~/.bash_profile
# agent 节点
# 查看 server 秘钥(master节点执行)
cat /var/lib/rancher/k3s/server/node-token
export INSTALL_K3S_VERSION=v1.22.7+k3s1
# 将上面查询的秘钥放在这里
export K3S_TOKEN=K10bff3ec9c28d2eeef4ece3b44d071d24jhhcf9d395e7b0af9e6a15711270fd292e6::server:d1bafa28603e1250fcf586b42cfciojhgg
# 安装脚本安装 ( 运行时参照 master 节点 )
curl -sfL http://rancher-mirror.cnrancher.com/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn K3S_URL=https://172.19.1.22:6443 K3S_TOKEN=K10bff3ec9c28d2eeef4ece3b44d071d24jhhcf9d395e7b0af9e6a15711270fd292e6::server:d1bafa28603e1250fcf586b42cfciojhgg sh -
2.1 安装NFS
# 在每个机器。
yum install -y nfs-utils
# 在master 执行以下命令
echo "/nfs/data/ *(insecure,rw,sync,no_root_squash)" > /etc/exports
# 执行以下命令,启动 nfs 服务;创建共享目录
mkdir -p /nfs/data
# 在master执行
systemctl enable rpcbind
systemctl enable nfs-server
systemctl start rpcbind
systemctl start nfs-server
安装默认nfs存储
kubectl apply -f nfs.yaml
文件 nfs.yaml
## 创建了一个存储类
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: nfs-storage
annotations:
storageclass.kubernetes.io/is-default-class: "true"
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner
parameters:
archiveOnDelete: "true" ## 删除pv的时候,pv的内容是否要备份
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-client-provisioner
labels:
app: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: default
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: nfs-client-provisioner
template:
metadata:
labels:
app: nfs-client-provisioner
spec:
serviceAccountName: nfs-client-provisioner
containers:
- name: nfs-client-provisioner
image: registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/nfs-subdir-external-provisioner:v4.0.2
# resources:
# limits:
# cpu: 10m
# requests:
# cpu: 10m
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME
value: k8s-sigs.io/nfs-subdir-external-provisioner
- name: NFS_SERVER
value: ## 指定自己nfs服务器地址
- name: NFS_PATH
value: /nfs/data ## nfs服务器共享的目录
volumes:
- name: nfs-client-root
nfs:
server: ## 指定自己nfs服务器地址
path: /nfs/data
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: default
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: nfs-client-provisioner-runner
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "watch", "update"]
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["events"]
verbs: ["create", "update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: run-nfs-client-provisioner
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: default
roleRef:
kind: ClusterRole
name: nfs-client-provisioner-runner
apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: default
rules:
- apiGroups: [""]
resources: ["endpoints"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: default
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: default
roleRef:
kind: Role
name: leader-locking-nfs-client-provisioner
apiGroup: rbac.authorization.k8s.io
3 签名证书
3.1 生成自签名证书
--ssl-domain: 生成ssl证书需要的主域名,如不指定则默认为www.rancher.local,如果是ip访问服务,则可忽略;
--ssl-trusted-ip: 一般ssl证书只信任域名的访问请求,有时候需要使用ip去访问server,那么需要给ssl证书添加扩展IP,多个IP用逗号隔开;
--ssl-trusted-domain: 如果想多个域名访问,则添加扩展域名(TRUSTED_DOMAIN),多个TRUSTED_DOMAIN用逗号隔开;
--ssl-size: ssl加密位数,默认2048;
--ssl-cn: 国家代码(2个字母的代号),默认CN;
使用示例:
./create_self-signed-cert.sh --ssl-domain=www.test.com --ssl-trusted-domain=www.test2.com \
--ssl-trusted-ip=1.1.1.1,2.2.2.2,3.3.3.3 --ssl-size=2048 --ssl-date=3650
# 添加证书到 k3s 集群
kubectl -n cattle-system create secret generic tls-ca --from-file=cacerts.pem=./cacerts.pem
生成ssl证书脚本文件 create_self-signed-cert.sh
(也可以去rancher官网查看)
#!/bin/bash -e
help ()
{
echo ' ================================================================ '
echo ' --ssl-domain: 生成ssl证书需要的主域名,如不指定则默认为www.rancher.local,如果是ip访问服务,则可忽略;'
echo ' --ssl-trusted-ip: 一般ssl证书只信任域名的访问请求,有时候需要使用ip去访问server,那么需要给ssl证书添加扩展IP,多个IP用逗号隔开;'
echo ' --ssl-trusted-domain: 如果想多个域名访问,则添加扩展域名(SSL_TRUSTED_DOMAIN),多个扩展域名用逗号隔开;'
echo ' --ssl-size: ssl加密位数,默认2048;'
echo ' --ssl-cn: 国家代码(2个字母的代号),默认CN;'
echo ' 使用示例:'
echo ' ./create_self-signed-cert.sh --ssl-domain=www.test.com --ssl-trusted-domain=www.test2.com \ '
echo ' --ssl-trusted-ip=1.1.1.1,2.2.2.2,3.3.3.3 --ssl-size=2048 --ssl-date=3650'
echo ' ================================================================'
}
case "$1" in
-h|--help) help; exit;;
esac
if [[ $1 == '' ]];then
help;
exit;
fi
CMDOPTS="$*"
for OPTS in $CMDOPTS;
do
key=$(echo ${OPTS} | awk -F"=" '{print $1}' )
value=$(echo ${OPTS} | awk -F"=" '{print $2}' )
case "$key" in
--ssl-domain) SSL_DOMAIN=$value ;;
--ssl-trusted-ip) SSL_TRUSTED_IP=$value ;;
--ssl-trusted-domain) SSL_TRUSTED_DOMAIN=$value ;;
--ssl-size) SSL_SIZE=$value ;;
--ssl-date) SSL_DATE=$value ;;
--ca-date) CA_DATE=$value ;;
--ssl-cn) CN=$value ;;
esac
done
# CA相关配置
CA_DATE=${CA_DATE:-3650}
CA_KEY=${CA_KEY:-cakey.pem}
CA_CERT=${CA_CERT:-cacerts.pem}
CA_DOMAIN=cattle-ca
# ssl相关配置
SSL_CONFIG=${SSL_CONFIG:-$PWD/openssl.cnf}
SSL_DOMAIN=${SSL_DOMAIN:-'www.rancher.local'}
SSL_DATE=${SSL_DATE:-3650}
SSL_SIZE=${SSL_SIZE:-2048}
## 国家代码(2个字母的代号),默认CN;
CN=${CN:-CN}
SSL_KEY=$SSL_DOMAIN.key
SSL_CSR=$SSL_DOMAIN.csr
SSL_CERT=$SSL_DOMAIN.crt
echo -e "\033[32m ---------------------------- \033[0m"
echo -e "\033[32m | 生成 SSL Cert | \033[0m"
echo -e "\033[32m ---------------------------- \033[0m"
if [[ -e ./${CA_KEY} ]]; then
echo -e "\033[32m ====> 1. 发现已存在CA私钥,备份"${CA_KEY}"为"${CA_KEY}"-bak,然后重新创建 \033[0m"
mv ${CA_KEY} "${CA_KEY}"-bak
openssl genrsa -out ${CA_KEY} ${SSL_SIZE}
else
echo -e "\033[32m ====> 1. 生成新的CA私钥 ${CA_KEY} \033[0m"
openssl genrsa -out ${CA_KEY} ${SSL_SIZE}
fi
if [[ -e ./${CA_CERT} ]]; then
echo -e "\033[32m ====> 2. 发现已存在CA证书,先备份"${CA_CERT}"为"${CA_CERT}"-bak,然后重新创建 \033[0m"
mv ${CA_CERT} "${CA_CERT}"-bak
openssl req -x509 -sha256 -new -nodes -key ${CA_KEY} -days ${CA_DATE} -out ${CA_CERT} -subj "/C=${CN}/CN=${CA_DOMAIN}"
else
echo -e "\033[32m ====> 2. 生成新的CA证书 ${CA_CERT} \033[0m"
openssl req -x509 -sha256 -new -nodes -key ${CA_KEY} -days ${CA_DATE} -out ${CA_CERT} -subj "/C=${CN}/CN=${CA_DOMAIN}"
fi
echo -e "\033[32m ====> 3. 生成Openssl配置文件 ${SSL_CONFIG} \033[0m"
cat > ${SSL_CONFIG} <<EOM
[req]
req_extensions = v3_req
distinguished_name = req_distinguished_name
[req_distinguished_name]
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, serverAuth
EOM
if [[ -n ${SSL_TRUSTED_IP} || -n ${SSL_TRUSTED_DOMAIN} || -n ${SSL_DOMAIN} ]]; then
cat >> ${SSL_CONFIG} <<EOM
subjectAltName = @alt_names
[alt_names]
EOM
IFS=","
dns=(${SSL_TRUSTED_DOMAIN})
dns+=(${SSL_DOMAIN})
for i in "${!dns[@]}"; do
echo DNS.$((i+1)) = ${dns[$i]} >> ${SSL_CONFIG}
done
if [[ -n ${SSL_TRUSTED_IP} ]]; then
ip=(${SSL_TRUSTED_IP})
for i in "${!ip[@]}"; do
echo IP.$((i+1)) = ${ip[$i]} >> ${SSL_CONFIG}
done
fi
fi
echo -e "\033[32m ====> 4. 生成服务SSL KEY ${SSL_KEY} \033[0m"
openssl genrsa -out ${SSL_KEY} ${SSL_SIZE}
echo -e "\033[32m ====> 5. 生成服务SSL CSR ${SSL_CSR} \033[0m"
openssl req -sha256 -new -key ${SSL_KEY} -out ${SSL_CSR} -subj "/C=${CN}/CN=${SSL_DOMAIN}" -config ${SSL_CONFIG}
echo -e "\033[32m ====> 6. 生成服务SSL CERT ${SSL_CERT} \033[0m"
openssl x509 -sha256 -req -in ${SSL_CSR} -CA ${CA_CERT} \
-CAkey ${CA_KEY} -CAcreateserial -out ${SSL_CERT} \
-days ${SSL_DATE} -extensions v3_req \
-extfile ${SSL_CONFIG}
echo -e "\033[32m ====> 7. 证书制作完成 \033[0m"
echo
echo -e "\033[32m ====> 8. 以YAML格式输出结果 \033[0m"
echo "----------------------------------------------------------"
echo "ca_key: |"
cat $CA_KEY | sed 's/^/ /'
echo
echo "ca_cert: |"
cat $CA_CERT | sed 's/^/ /'
echo
echo "ssl_key: |"
cat $SSL_KEY | sed 's/^/ /'
echo
echo "ssl_csr: |"
cat $SSL_CSR | sed 's/^/ /'
echo
echo "ssl_cert: |"
cat $SSL_CERT | sed 's/^/ /'
echo
echo -e "\033[32m ====> 9. 附加CA证书到Cert文件 \033[0m"
cat ${CA_CERT} >> ${SSL_CERT}
echo "ssl_cert: |"
cat $SSL_CERT | sed 's/^/ /'
echo
echo -e "\033[32m ====> 10. 重命名服务证书 \033[0m"
echo "cp ${SSL_DOMAIN}.key tls.key"
cp ${SSL_DOMAIN}.key tls.key
echo "cp ${SSL_DOMAIN}.crt tls.crt"
cp ${SSL_DOMAIN}.crt tls.crt
3.2 验证证书
openssl verify -CAfile cacerts.pem tls.crt` 应该返回状态为 `ok
openssl x509 -in tls.crt -noout -text执行后查看对应的域名和扩展 iP 是否正确
3.2 添加 Kubernetes TLS 密文
使用私有 CA 签发证书
kubectl -n cattle-system create secret tls tls-rancher-ingress \
--cert=tls.crt \
--key=tls.key
kubectl -n cattle-system create secret generic tls-ca \
--from-file=cacerts.pem=./cacerts.pem
4 安装 Rancher
4.1 添加 Helm Chart 仓库
使用 helm repo add 命令添加包含 Rancher Chart 的 Helm 仓库来安装 Rancher。
请替换命令中的<CHART_REPO>,替换为latest,stable或alpha。更多信息,请查看选择 rancher 版本来选择最适合您的仓库。
latest: 推荐在尝试新功能时使用。
stable: 推荐生产环境中使用。(推荐)
alpha: 未来版本的实验性预览。
helm repo add rancher-<CHART_REPO> https://releases.rancher.com/server-charts/<CHART_REPO>
rancher 版本如下:
| 类别 | 添加仓库命令 | 仓库描述 |
|---|---|---|
| rancher-latest | helm repo add rancher-latest https://releases.rancher.com/server-charts/latest | 添加最新版本的 Rancher 的 Helm Chart 仓库。我们建议使用此仓库来测试新版本的 Rancher。 |
| rancher-stable | helm repo add rancher-stable https://releases.rancher.com/server-charts/stable | 添加较旧的,稳定的版本的 Rancher 的 Helm Chart 仓库。我们建议将此仓库用于生产环境。 |
| rancher-alpha | helm repo add rancher-alpha https://releases.rancher.com/server-charts/alpha | 添加 alpha 版本的 Rancher 的 Helm Chart 仓库,以预览即将发布的版本.不建议在生产环境中使用这些版本。我们不支持从 rancher alpha 仓库中的 chart 升级到任何其他版本 chart。 |
4.2 选择 SSL 配置
Rancher Server 默认需要 SSL/TLS 配置来保证访问的安全性。
以下有三种关于证书来源的推荐选项。
提示: 如果您想要将 SSL/TLS 访问在外部终止,请查看使用外部 TLS 负载均衡器。
| 设置 | Chart 选项 | 描述 | 是否需要 cert-manager |
|---|---|---|---|
| Rancher 自签名证书 | ingress.tls.source=rancher | 使用 Rancher 生成的 CA 签发的自签名证书此项为默认选项 | 是 |
| Let’s Encrypt | ingress.tls.source=letsEncrypt | 使用Let’s Encrypt颁发的证书 | 是 |
| 您已有的证书 | ingress.tls.source=secret | 使用您的已有证书(Kubernetes 密文) | 否 |
注意: rancher-latest 和 rancher-stable Helm Chart 仓库是在 Rancher v2.1.0 后引入的,因此rancher-stable仓库包含一些从来没有被标记为rancher/rancher:stable标签的 Rancher 版本。在 v2.1.0 之前标记为rancher/rancher:stable的 Rancher 版本是 v2.0.4,v2.0.6,v2.0.8。在 v2.1.0 版本之后,rancher-stable仓库中的所有 charts 将与标记为stable的 Rancher 版本对应。
4.4 已有的证书安装
- 设置 hostname 并且将 ingress.tls.source 选项设置为 secret。
- 如果您在安装 alpha 版本,需要把–devel 选项添加到下面到 Helm 命令中。
helm install rancher-<CHART_REPO>/rancher \
--name rancher \
--namespace cattle-system \
--set hostname=rancher.my.org \
--set ingress.tls.source=secret
如果您使用的是私有 CA 证书,请在命令中增加 --set privateCA=true
helm install rancher-<CHART_REPO>/rancher \
--name rancher \
--namespace cattle-system \
--set hostname=rancher.my.org \
--set ingress.tls.source=secret
--set privateCA=true
如果是v2.6.x 版本 需要添加 --set bootstrapPassword=Passw0rd
helm install rancher rancher-stable/rancher \
--namespace cattle-system \
--set hostname=rancher.moresec.cn \
--set ingress.tls.source=secret \
--set privateCA=true \
--set bootstrapPassword=Passw0rd
4.5 获取登录密码
# docker安装获取
docker logs container-id 2>&1 | grep "Bootstrap Password:"
# helm 安装获取
kubectl get secret --namespace cattle-system bootstrap-secret -o go-template='{{.data.bootstrapPassword|base64decode}}{{"\n"}}'
# 如果获取不到 重置密码
kubectl -n cattle-system exec $(kubectl -n cattle-system get pods -l app=rancher | grep '1/1' | head -1 | awk '{ print $1 }') -- reset-password
5 k3s 的 containerd 私有仓库地址配置
K3s 是一个轻量级 Kubernetes 发行版,二进制大小小于100MB,所需内存不到Kubernetes的一半。K3s 为了降低资源消耗,将默认的 runtime 修改为 containerd,同时也内置了 Kubernetes CLI 工具 crictl和ctr。
K3s 默认的 containerd 配置文件目录为/var/lib/rancher/k3s/agent/etc/containerd/config.toml,但直接操作 containerd 的配置文件去设置镜像仓库或加速器相比于操作 docker 要复杂许多。K3s 为了简化配置 containerd 镜像仓库的复杂度,K3s 会在启动时检查/etc/rancher/k3s/中是否存在 registries.yaml 文件,如果存在该文件,就会根据 registries.yaml 的内容转换为 containerd 的配置并存储到/var/lib/rancher/k3s/agent/etc/containerd/config.toml,从而降低了配置 containerd 镜像仓库的复杂度。
5.1 生成签名证书
host=docker-mirror.internal
port=443
openssl s_client -showcerts -connect ${host}:${port} < /dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p'
将生成证书 复制到 文件 docker-mirror.crt 内
并拷贝一份到 /etc/ssl/certs.d/
具体原因还要在研究
5.2 使用 K3s 配置私有镜像仓库
K3s 镜像仓库配置文件由两大部分组成:mirrors和configs:
- Mirrors 是一个用于定义专用镜像仓库的名称 endpoint 的指令
- Configs 部分定义了每个 mirror 的 TLS 和证书配置。对于每个 mirror,你可以定义auth和/或tls
containerd 使用了类似 K8S 中 svc 与 endpoint 的概念,svc 可以理解为访问名称,这个名称会解析到对应的 endpoint 上。也可以理解 mirror 配置就是一个反向代理,它把客户端的请求代理到 endpoint 配置的后端镜像仓库。mirror 名称可以随意填写,但是必须符合IP或域名的定义规则。并且可以配置多个 endpoint,默认解析到第一个 endpoint,如果第一个 endpoint 没有返回数据,则自动切换到第二个 endpoint,以此类推。
使用自签 ssl 证书
文件位置:/etc/rancher/k3s/registries.yaml
mirrors:
"harbor-ksd.kingsd.top":
endpoint:
- "https://harbor-ksd.kingsd.top"
configs:
"harbor-ksd.kingsd.top":
auth:
username: admin # this is the registry username
password: Harbor12345 # this is the registry password
tls:
ca_file: /opt/certs/ca.crt
# 重启服务
systemctl restart k3s
5.3 (官方版)生成默认配置文件
containerd config default > /etc/containerd/config.toml
# 'plugins."io.containerd.grpc.v1.cri".registry' contains config related to
# the registry
[plugins."io.containerd.grpc.v1.cri".registry]
# config_path specifies a directory to look for the registry hosts configuration.
#
# The cri plugin will look for and use config_path/host-namespace/hosts.toml
# configs if present OR load certificate files as laid out in the Docker/Moby
# specific layout https://docs.docker.com/engine/security/certificates/
#
# If config_path is not provided defaults are used.
#
# *** registry.configs and registry.mirrors that were a part of containerd 1.4
# are now DEPRECATED and will only be used if the config_path is not specified.
config_path = "/etc/containerd/certs.d"
containerd github 配置文件
配置 config_path = “/etc/containerd/certs.d”
解释一下: 只需要配置 config_path 仓库配置文件目录,其他不用配置,registry.configs 和 registry.mirrors 插件配置已经在 containerd 1.4 以后已经废弃了
5.3.1 配置仓库配置
目录结构
$ tree /etc/containerd/certs.d
/etc/containerd/certs.d
└── registry-1.docker.io
└── hosts.toml
$ cat /etc/containerd/certs.d/registry-1.docker.io/hosts.toml
server = "https://registry-1.docker.io" # Exclude this to not use upstream
[host."https://public-mirror.example.com"]
capabilities = ["pull"] # Requires less trust, won't resolve tag to digest from this host
[host."https://docker-mirror.internal"]
capabilities = ["pull", "resolve"]
ca = "docker-mirror.crt" # Or absolute path /etc/containerd/certs.d/docker.io/docker-mirror.crt
5.3.2 重启服务
systemctl daemon-reload
systemctl restart containerd
6 FAQ
6.1 cgroup 不一致问题
error: failed to run Kubelet: failed to create kubelet: misconfiguration: kubelet cgroup driver: “cgroupfs” is different from docker cgroup driver: “systemd”
解决办法 : 修改docker,只需在/etc/docker/daemon.json中,添加"exec-opts": [“native.cgroupdriver=cgroupfs”]即可
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"exec-opts": [“native.cgroupdriver=cgroupfs”]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
sudo systemctl restart k3s
7 参考文献
- 感谢你赐予我前进的力量

