kubernetes的master是需要配置高可用集群的,当一台master出问题了之后另外一台master仍然是可以继续工作的。比如下图

不管是worker还是client,只要把请求发送到LB负载均衡器,然后LB会把请求在master1和master2之间进行转发。这里只要有一个master能够正常工作,整个kubernetes集群就会正常工作。
master1和master2需要实时同步数据,利用的是etcd集群的数据同步,在kubernetes官网提供了两种etcd同步的方案,一个是使用内部etcd集群,一个是使用的外部etcd集群。下面分别来演示这两种实验步骤。
官网提供的实验拓扑图如下

官网提供的拓扑图里有三台master,每台master上的etcd都是以pod的方式运行的,当建立好三台master之后,三台master上的etcd会自动建立成etcd集群。
本实验用两台master,拓扑图如下。

步骤1:在vms80上安装haproxy
yum install haproxy -y
修改/etc/haproxy/haproxy.cfg,在最后面添加如下内容
listen k8s-lb *:6443
mode tcp
balance roundrobin
server s1 192.168.26.81:6443 weight 1
server s2 192.168.26.82:6443 weight 1
启动haproxy并设置开机自动启动
systemctl enable haproxy --now
这样当把请求转发给192.168.26.80:6443的时候,vms80会把请求转发到vms81和vms82的6443端口。
步骤2:安装containerd安装k8s
这里安装和配置containerd、安装kubernetes相关软件、修改内核参数、加载模块等操作这些步骤不是重点,这里忽略,大家自行操作。
步骤3:编写配置文件
在vms81上,通过命令kubeadm config print init-defaults > config.yaml 获取初始化集群的配置文件,并修改成如下这个样子
apiServer:
extraArgs:
authorization-mode: Node,RBAC
timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta3
certificatesDir: /etc/kubernetes/pki
controlPlaneEndpoint: "192.168.26.80:6443"
clusterName: kubernetes
controllerManager: {}
dns: {}
etcd:
local:
dataDir: /var/lib/etcd
imageRepository: registry.aliyuncs.com/google_containers
kind: ClusterConfiguration
kubernetesVersion: v1.26.1
networking:
dnsDomain: cluster.local
podSubnet: 10.244.0.0/16
serviceSubnet: 10.96.0.0/12
scheduler: {}
注意这里添加了controlPlaneEndpoint: “192.168.26.80:6443” 用于指定haproxy的地址和端口,同时注意这里的etcd的配置都是本地的。
步骤4:在vms81上初始化集群
执行下面命令初始化集群
kubeadm init --config=./config.yaml
之后按提示拷贝kubeconfig文件
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
这样第一台master就安装完毕了。
步骤5:把所需要的证书拷贝到vms82
先把需要的证书名及路径写入到aa.txt
[root@vms81 ~]# cat aa.txt
/etc/kubernetes/pki/ca.crt
/etc/kubernetes/pki/ca.key
/etc/kubernetes/pki/sa.key
/etc/kubernetes/pki/sa.pub
/etc/kubernetes/pki/front-proxy-ca.crt
/etc/kubernetes/pki/front-proxy-ca.key
/etc/kubernetes/pki/etcd/ca.key
/etc/kubernetes/pki/etcd/ca.crt
[root@vms81 ~]#
然后用tar命令把aa.txt里指定的文件压缩到cert.tar.gz里。
tar czf cert.tar.gz -T aa.txt
cert.tar.gz的内容如下
[root@vms81 ~]# tar tf cert.tar.gz
etc/kubernetes/pki/ca.crt
etc/kubernetes/pki/ca.key
etc/kubernetes/pki/sa.key
etc/kubernetes/pki/sa.pub
etc/kubernetes/pki/front-proxy-ca.crt
etc/kubernetes/pki/front-proxy-ca.key
etc/kubernetes/pki/etcd/ca.key
etc/kubernetes/pki/etcd/ca.crt
[root@vms81 ~]#
把压缩的证书拷贝到vms82上。
scp cert.tar.gz 192.168.26.82:~
切换到vms82上,解压cert.tar.gz
tar zxf cert.tar.gz -C /
查看证书
[root@vms82 ~]# ls /etc/kubernetes/pki/
ca.crt ca.key etcd front-proxy-ca.crt front-proxy-ca.key sa.key sa.pub
[root@vms82 ~]# ls /etc/kubernetes/pki/etcd/
ca.crt ca.key
[root@vms82 ~]#
在vms82上该有的证书都有了。
步骤6:把vms82以控制平面节点的方式加入集群
敲如下命令把vms82加入集群(vms81集群初始化完成之后会提示如下命令)
kubeadm join 192.168.26.80:6443 --token ynacxs.5whmmtkpjc87d7f5 --discovery-token-ca-cert-hash sha256:abaad7129786ebd8d5e5dea1f99e7311ebdd0875455ead58163dda425c353b81 --control-plane
上述命令最后有一个–control-plane,意思就是以控制平面节点的方式加入集群。
之后按提示复制kubeconfig文件(在vms82上做)
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
步骤7:通过kubectl get nodes查看
不管在vms81上还是vms82上执行kubectl get nodes查看

步骤8:把worker加入节点
在vms83上以worker的方式加入集群
kubeadm join 192.168.26.80:6443 --token ynacxs.5whmmtkpjc87d7f5 --discovery-token-ca-cert-hash sha256:abaad7129786ebd8d5e5dea1f99e7311ebdd0875455ead58163dda425c353b81
切换到vms81或者vms82上通过kubectl get nodes查看

查看kube-system里的etcd,会发现两台master上的etcd自动建立了集群。

然后安装calico之后集群即可正常工作,这里忽略。
步骤9:为了方法2的练习做准备,下面清空集群
[root@vms81 ~]# kubectl delete node vms83.rhce.cc
[root@vms81 ~]# kubectl delete node vms82.rhce.cc
[root@vms81 ~]# kubectl delete node vms81.rhce.cc
在所有节点执行kubeadm reset,准备第二种方法。
官网提供的拓扑图如下

这里每个etcd是以外部集群的方式存在的,而不是以pod的方式运行。我们练习的拓扑图如下

为了节约机器,这里etcd1放在vms81上运行,etcd2放在vms82上运行。
因为要实现etcd集群和master之间的mTLS通信,这里需要在两台etcd上配置证书。
步骤1:准备cfssl工具
下载cfssl工具放在/usr/local/bin/里
下载地址
https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
之后把下载下来的文件的后缀_linux-amd64去除并加上x权限
for i in * ; do n=${i%_*} ; mv $i $n; done ; chmod +x *
步骤2:创建证书
创建etcd证书所能用到的目录,并进入到此目录里。
mkdir -p /etc/kubernetes/pki/etcd ; cd /etc/kubernetes/pki/etcd
创建ca的配置文件ca-config.json,内容如下。
{
"signing": {
"default": {
"expiry": "43800h"
},
"profiles": {
"server": {
"expiry": "43800h",
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
]
},
"client": {
"expiry": "43800h",
"usages": [
"signing",
"key encipherment",
"client auth"
]
},
"peer": {
"expiry": "43800h",
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
]
}
}
}
}
创建ca证书的请求文件ca-csr.json,内容如下。
{
"CN": "etcd",
"key": {
"algo": "rsa",
"size": 2048
}
}
创建etcd客户端(apiserver就是etcd的客户端)用的证书请求文件client.json,内容如下。
{
"CN": "client",
"key": {
"algo": "ecdsa",
"size": 256
}
}
已经创建的文件如下。
[root@vms81 etcd]# ls
ca-config.json ca-csr.json client.json
[root@vms81 etcd]#
生成CA证书和私钥。
cfssl gencert -initca ca-csr.json | cfssljson -bare ca -
生成etcd客户端能用到的证书和私钥(apiserver就是etcd的客户端)
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=client client.json | cfssljson -bare client
现在目录里的内容如下
[root@vms81 etcd]# ls
ca-config.json ca-csr.json ca.pem
client.json client.pem ca.csr
ca-key.pem client.csr client-key.pem
[root@vms81 etcd]#
把这些证书拷贝到其他所有master上(这里是要拷贝到vms82上)
scp -r /etc/kubernetes/pki/ 192.168.26.82:/etc/kubernetes/
步骤3:生成etcd服务器端的证书,以及etcd节点之间建立peer的证书
在所有master节点上进入到/etc/kubernetes/pki/etcd目录里,执行如下命令。
cd /etc/kubernetes/pki/etcd
export PEER_NAME=$(hostname)
export PRIVATE_IP=$(ip addr show ens32 | grep -Po 'inet \K[\d.]+')
cfssl print-defaults csr > config.json
sed -i 's/www\.example\.net/'"$PRIVATE_IP"'/' config.json
sed -i 's/example\.net/'"$PEER_NAME"'/' config.json
sed -i '0,/CN/{s/example\.net/'"$PEER_NAME"'/}' config.json
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=server config.json | cfssljson -bare server
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=peer config.json | cfssljson -bare peer
这里涉及到的证书比较多,总结如下图。

客户端(apiserver)和etcd通信的时候,利用到client的密钥和etcd的server两个密钥进行验证。两台etcd服务器之间用peer的证书 进行验证。
步骤4:在所有节点建立etcd的变量文件
在所有节点上执行
export PEER_NAME=$(hostname)
export PRIVATE_IP=$(ip addr show ens32 | grep -Po 'inet \K[\d.]+')
touch /etc/etcd.env
echo "PEER_NAME=$PEER_NAME" >> /etc/etcd.env
echo "PRIVATE_IP=$PRIVATE_IP" >> /etc/etcd.env
查看vms81上的变量文件
[root@vms81 ~]# cat /etc/etcd.env
PEER_NAME=vms81.rhce.cc
PRIVATE_IP=192.168.26.81
[root@vms81 ~]#
查看vms82上的变量文件
[root@vms82 etcd]# cat /etc/etcd.env
PEER_NAME=vms82.rhce.cc
PRIVATE_IP=192.168.26.82
[root@vms82 etcd]#
步骤5:所有节点安装配置etcd
在所有节点上安装etcd
yum install etcd -y
所有节点编写etcd的启动脚本,vms81上的内容如下。
[root@vms81 ~]# cat /usr/lib/systemd/system/etcd.service
[Unit]
Description=etcd
Documentation=https://github.com/coreos/etcd
Conflicts=etcd.service
Conflicts=etcd2.service
[Service]
EnvironmentFile=/etc/etcd.env
Type=notify
Restart=always
RestartSec=5s
LimitNOFILE=40000
TimeoutStartSec=0
ExecStart=/bin/etcd --name vms81 \
--data-dir /var/lib/etcd \
--listen-client-urls https://${PRIVATE_IP}:2379,https://127.0.0.1:2379 \
--advertise-client-urls https://${PRIVATE_IP}:2379 \
--listen-peer-urls https://${PRIVATE_IP}:2380 \
--initial-advertise-peer-urls https://${PRIVATE_IP}:2380 \
--cert-file=/etc/kubernetes/pki/etcd/server.pem \
--key-file=/etc/kubernetes/pki/etcd/server-key.pem \
--trusted-ca-file=/etc/kubernetes/pki/etcd/ca.pem \
--peer-cert-file=/etc/kubernetes/pki/etcd/peer.pem \
--peer-key-file=/etc/kubernetes/pki/etcd/peer-key.pem \
--peer-trusted-ca-file=/etc/kubernetes/pki/etcd/ca.pem \
--initial-cluster vms81=https://192.168.26.81:2380,vms82=https://192.168.26.82:2380 \
--initial-cluster-token my-etcd-token \
--initial-cluster-state new \
--client-cert-auth=false \
--peer-client-cert-auth=false
[Install]
WantedBy=multi-user.target
[root@vms81 ~]#
vms82上的内容如下。
[root@vms82 ~]# cat /usr/lib/systemd/system/etcd.service
[Unit]
Description=etcd
Documentation=https://github.com/coreos/etcd
Conflicts=etcd.service
Conflicts=etcd2.service
[Service]
EnvironmentFile=/etc/etcd.env
Type=notify
Restart=always
RestartSec=5s
LimitNOFILE=40000
TimeoutStartSec=0
ExecStart=/bin/etcd --name vms82 \
--data-dir /var/lib/etcd \
--listen-client-urls https://${PRIVATE_IP}:2379,https://127.0.0.1:2379 \
--advertise-client-urls https://${PRIVATE_IP}:2379 \
--listen-peer-urls https://${PRIVATE_IP}:2380 \
--initial-advertise-peer-urls https://${PRIVATE_IP}:2380 \
--cert-file=/etc/kubernetes/pki/etcd/server.pem \
--key-file=/etc/kubernetes/pki/etcd/server-key.pem \
--trusted-ca-file=/etc/kubernetes/pki/etcd/ca.pem \
--peer-cert-file=/etc/kubernetes/pki/etcd/peer.pem \
--peer-key-file=/etc/kubernetes/pki/etcd/peer-key.pem \
--peer-trusted-ca-file=/etc/kubernetes/pki/etcd/ca.pem \
--initial-cluster vms81=https://192.168.26.81:2380,vms82=https://192.168.26.82:2380 \
--initial-cluster-token my-etcd-token \
--initial-cluster-state new \
--client-cert-auth=false \
--peer-client-cert-auth=false
[Install]
WantedBy=multi-user.target
[root@vms82 ~]#
在所有节点上启动etcd
systemctl daemon-reload ; systemctl start etcd
查看etcd集群健康状态。

步骤6:建立初始化集群的初始化文件
修改config.yaml内容如下。
[root@vms81 ~]# cat config.yaml
apiServer:
extraArgs:
authorization-mode: Node,RBAC
timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta3
certificatesDir: /etc/kubernetes/pki
controlPlaneEndpoint: "192.168.26.80:6443"
clusterName: kubernetes
controllerManager: {}
dns: {}
etcd:
external:
endpoints:
- "https://192.168.26.81:2379"
- "https://192.168.26.82:2379"
caFile: /etc/kubernetes/pki/etcd/ca.pem
certFile: /etc/kubernetes/pki/etcd/client.pem
keyFile: /etc/kubernetes/pki/etcd/client-key.pem
imageRepository: registry.aliyuncs.com/google_containers
kind: ClusterConfiguration
kubernetesVersion: v1.26.1
networking:
dnsDomain: cluster.local
podSubnet: 10.244.0.0/16
serviceSubnet: 10.96.0.0/12
scheduler: {}
[root@vms81 ~]#
注意这里etcd部分,指定了etcd集群每台主机的地址,以及指定了apiserver所能用的证书。
步骤7:初始化集群
kubeadm init --config=config.yaml
初始化完毕之后按提示复制kubeconfig文件,因为本机器之前用过,所以在cp的时候提示是否覆盖,输入y。
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
步骤8:把vms81上所需要的证书拷贝到vms82上
把所需要的证书放在aa.txt,注意这里aa.txt的内容跟方法1里的aa.txt的内容有变化。
[root@vms81 ~]# vim aa.txt
[root@vms81 ~]# cat aa.txt
/etc/kubernetes/pki/ca.crt
/etc/kubernetes/pki/ca.key
/etc/kubernetes/pki/sa.key
/etc/kubernetes/pki/sa.pub
/etc/kubernetes/pki/front-proxy-ca.crt
/etc/kubernetes/pki/front-proxy-ca.key
[root@vms81 ~]#
把aa.txt里列出的证书打包到cert.tar.gz里
tar czf cert.tar.gz -T aa.txt
查看cert.tar.gz里的内容。
[root@vms81 ~]# tar tf cert.tar.gz
etc/kubernetes/pki/ca.crt
etc/kubernetes/pki/ca.key
etc/kubernetes/pki/sa.key
etc/kubernetes/pki/sa.pub
etc/kubernetes/pki/front-proxy-ca.crt
etc/kubernetes/pki/front-proxy-ca.key
[root@vms81 ~]#
把cert.tar.gz拷贝到vms82是哪个。
scp cert.tar.gz 192.168.26.82:~
到vms82上,解压
tar zxf cert.tar.gz -C /
步骤8:vms82以控制节点的方式加入到集群
kubeadm join 192.168.26.80:6443 --token z1jl6r.sh3g9ebulj3b97vz --discovery-token-ca-cert-hash sha256:3c9282325e761196a06583ac1308da85c5596ed025d7bb87a0b26217ba64db52 --control-plane
之后按提示复制kubeconfig文件。
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
步骤9:验证
在vms81或者vms82上执行kubectl get nodes命令

把vms83加入集群,在vms83上执行如下命令
kubeadm join 192.168.26.80:6443 --token z1jl6r.sh3g9ebulj3b97vz --discovery-token-ca-cert-hash sha256:3c9282325e761196a06583ac1308da85c5596ed025d7bb87a0b26217ba64db52
再次在vms81或者vms82上验证

之后自行安装calico即可。
我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po
我打算为ruby脚本创建一个安装程序,但我希望能够确保机器安装了RVM。有没有一种方法可以完全离线安装RVM并且不引人注目(通过不引人注目,就像创建一个可以做所有事情的脚本而不是要求用户向他们的bash_profile或bashrc添加一些东西)我不是要脚本本身,只是一个关于如何走这条路的快速指针(如果可能的话)。我们还研究了这个很有帮助的问题:RVM-isthereawayforsimpleofflineinstall?但有点误导,因为答案只向我们展示了如何离线在RVM中安装ruby。我们需要能够离线安装RVM本身,并查看脚本https://raw.github.com/wayn
我有一个奇怪的问题:我在rvm上安装了rubyonrails。一切正常,我可以创建项目。但是在我输入“railsnew”时重新启动后,我有“程序'rails'当前未安装。”。SystemUbuntu12.04ruby-v"1.9.3p194"gemlistactionmailer(3.2.5)actionpack(3.2.5)activemodel(3.2.5)activerecord(3.2.5)activeresource(3.2.5)activesupport(3.2.5)arel(3.0.2)builder(3.0.0)bundler(1.1.4)coffee-rails(
我刚刚为fedora安装了emacs。我想用emacs编写ruby。为ruby提供代码提示、代码完成类型功能所需的工具、扩展是什么? 最佳答案 ruby-mode已经包含在Emacs23之后的版本中。不过,它也可以通过ELPA获得。您可能感兴趣的其他一些事情是集成RVM、feature-mode(Cucumber)、rspec-mode、ruby-electric、inf-ruby、rinari(用于Rails)等。这是我当前用于Ruby开发的Emacs配置:https://github.com/citizen428/emacs
我正在尝试在我的centos服务器上安装therubyracer,但遇到了麻烦。$geminstalltherubyracerBuildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingtherubyracer:ERROR:Failedtobuildgemnativeextension./usr/local/rvm/rubies/ruby-1.9.3-p125/bin/rubyextconf.rbcheckingformain()in-lpthread...yescheckingforv8.h...no***e
我的最终目标是安装当前版本的RubyonRails。我在OSXMountainLion上运行。到目前为止,这是我的过程:已安装的RVM$\curl-Lhttps://get.rvm.io|bash-sstable检查已知(我假设已批准)安装$rvmlistknown我看到当前的稳定版本可用[ruby-]2.0.0[-p247]输入命令安装$rvminstall2.0.0-p247注意:我也试过这些安装命令$rvminstallruby-2.0.0-p247$rvminstallruby=2.0.0-p247我很快就无处可去了。结果:$rvminstall2.0.0-p247Search
我实际上是在尝试使用RVM在我的OSX10.7.5上更新ruby,并在输入以下命令后:rvminstallruby我得到了以下回复:Searchingforbinaryrubies,thismighttakesometime.Checkingrequirementsforosx.Installingrequirementsforosx.Updatingsystem.......Errorrunning'requirements_osx_brew_update_systemruby-2.0.0-p247',pleaseread/Users/username/.rvm/log/138121
由于fast-stemmer的问题,我很难安装我想要的任何rubygem。我把我得到的错误放在下面。Buildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingfast-stemmer:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcreatingMakefilemake"DESTDIR="cleanmake"DESTDIR=
我在app/helpers/sessions_helper.rb中有一个帮助程序文件,其中包含一个方法my_preference,它返回当前登录用户的首选项。我想在集成测试中访问该方法。例如,这样我就可以在测试中使用getuser_path(my_preference)。在其他帖子中,我读到这可以通过在测试文件中包含requiresessions_helper来实现,但我仍然收到错误NameError:undefinedlocalvariableormethod'my_preference'.我做错了什么?require'test_helper'require'sessions_hel
我有用于控制用户任务的Rails5API项目,我有以下错误,但并非总是针对相同的Controller和路由。ActionController::RoutingError:uninitializedconstantApi::V1::ApiController我向您描述了一些我的项目,以更详细地解释错误。应用结构路线scopemodule:'api'donamespace:v1do#=>Loginroutesscopemodule:'login'domatch'login',to:'sessions#login',as:'login',via::postend#=>Teamroutessc