在上个章节中,我们介绍了如何使用Azure Container Service Engine部署一个DCOS集群,这篇文章我们主要介绍一下如何使用acs engine在Azure中国区部署一个Kubernetes集群。
Kubernetes是Google开源的容器集群管理系统。它构建于docker技术之上,为容器化的应用提供资源调度、部署运行、服务发现、扩容缩容等整一套功能。下图是一张Kubernetes架构总览:
Kubernetes以RESTful形式开放接口,用户可操作的核心对象有三个:
pod:是Kubernetes最基本的部署调度单元,可以包含container,逻辑上表示某种应用的一个实例。比如一个web站点应用由前端、后端及数据库构建而成,这三个组件将运行在各自的容器中,那么我们可以创建包含三个container的pod。
service:是pod的路由代理抽象,用于解决pod之间的服务发现问题。因为pod的运行状态可动态变化(比如切换机器了、缩容过程中被终止了等),所以访问端不能以写死IP的方式去访问该pod提供的服务。service的引入旨在保证pod的动态变化对访问端透明,访问端只需要知道service的地址,由service来提供代理。
replication controller:是pod的复制抽象,用于解决pod的扩容缩容问题。通常,分布式应用为了性能或高可用性的考虑,需要复制多份资源,并且根据负载情况动态伸缩。通过replication controller,我们可以指定一个应用需要几份复制,Kubernetes将为每份复制创建一个pod,并且保证实际运行pod数量总是与该复制数量相等(例如,当前某个pod宕机时,自动创建新的pod来替换)。
可以看到,service和replication controller只是建立在pod之上的抽象,最终是要作用于pod的,那么它们如何跟pod联系起来呢?这就要引入label的概念:label其实很好理解,就是为pod加上可用于搜索或关联的一组key/value标签,而service和replication controller正是通过label来与pod关联的。如下图所示,有三个pod都有label为”app=backend”,创建service和replication Controller时可以指定同样的label:”app=backend”,再通过label selector机制,就将它们与这三个pod关联起来了。例如,当有其他frontend pod访问该service时,自动会转发到其中的一个backend pod。
如下图所示是官方文档里的集群架构图,一个典型的master/slave模型。
master运行三个组件:
slave(称作minion)运行两个组件:
了解完kubernetes大致的结构以后,我们就可以开始部署Kubernetes集群了。
由于国内外网络情况的差异,默认的acs engine是无法顺利在Azure中国区部署的,我们需要对源码进行少量的修改,将默认对google和docker的依赖组件镜像到国内才能顺利部署。这些修改大体上包含如下几步:
这个service principal的主要目的是让kubernetes有权限访问Azure,并在其中为kubernetes集群中的service创建对应的负载均衡。
1. 登录Azure经典管理门户,点击Active Directory
2. 点击选择对应的AD,进入配置主界面
3. 点击“应用程序”按钮,创建一个新的应用程序
4. 根据弹出的创建向导,创建对应的应用程序
5. 应用创建好以后,点击“配置”按钮,可以看到“客户端ID”已经有了。
6. 在“密钥”处,点选“1年”,然后保存,这时密钥就创建好了
通过以上的步骤,ACS engine中需要的service principal就创建好了,我们需要将这两个字段保存下来,后面的步骤中就会用到。
{
"apiVersion": "vlabs",
"properties": {
"orchestratorProfile": {
"orchestratorType":"Kubernetes"
},
"masterProfile": {
"count": 1,
"dnsPrefix":"test-m01",
"vmSize":"Standard_D2_v2"
},
"agentPoolProfiles": [
{
"name":"agentpool1",
"count": 3,
"vmSize":"Standard_D2_v2",
"availabilityProfile":"AvailabilitySet"
}
],
"linuxProfile": {
"adminUsername":"azureuser",
"ssh": {
"publicKeys": [
{
"keyData": "XXXXXXXXXXXXXXXXXX(SSH KEY)" }
]
}
},
"servicePrincipalProfile": {
"servicePrincipalClientID":"(上一步中生成的客户端ID)",
"servicePrincipalClientSecret": "(上一步中生成的密钥)"
}
}
}
标红的地方是我们需要修改的,修改好后保存就可以进行下一步了。
默认的acs engine是不支持Azure中国区的,不过这并不影响我们修改它的代码让它满足在其上部署,首先我们在pkg/acsengine/azureconst.go中找到AzureLocations数组,并在其末尾添加中国的两个数据中心:”chinanorth”, “chinaeast”。
var AzureLocations = []string{
"australiaeast",
"australiasoutheast",
……
"westeurope",
"westindia",
"westus",
"westus2",
"chinanorth",
"chinaeast"
}
另外,中国区的域名后缀和海外的Azure也不太一样,在azureconst.go文件中找到AzureProdFQDNFormat配置项,把它从“%s.%s.cloudapp.azure.com”改成“%s.%s.cloudapp.chinacloudapi.cn”
const(
AzureProdFQDNFormat ="%s.%s.cloudapp.chinacloudapi.cn"
)
默认的配置会去访问Azure的AD的海外节点“login.windows.net”,我们需要将它修改为访问Azure中国的“login.chinacloudapi.cn”。 在这个脚本中找到如下的代码,并在其中增加cloud: “AzureChinaCloud”配置即可切换过来。
cat<< EOF > "${AZURE_JSON_PATH}"
{
"cloud":"AzureChinaCloud",
"tenantId":"${TENANT_ID}",
"subscriptionId":"${SUBNETSCRIPTION_ID}",
"aadClientId":"${SERVICE_PRINCIPAL_CLIENT_ID}",
"aadClientSecret":"${SERVICE_PRINCIPAL_CLIENT_SECRET}",
"resourceGroup":"${RESOURCE_GROUP}",
"location":"${LOCATION}",
"subnetName":"${SUBNET}",
"securityGroupName":"${NETWORK_SECURITY_GROUP}",
"vnetName":"${VIRTUAL_NETWORK}",
"routeTableName":"${ROUTE_TABLE}",
"primaryAvailabilitySetName":"${PRIMARY_AVAILABILITY_SET}"
}
runcmd:
- /bin/bash -c "/bin/echoDAEMON_ARGS=--advertise-client-urls ""http://127.0.0.1:2379,http://{{{masterPrivateIp}}}:2379""--listen-client-urls""http://0.0.0.0:2379,http://0.0.0.0:4001"" | tee -a/etc/default/etcd"
- /usr/bin/curl -sSL --retry 12--retry-delay 10 https://get.docker.com/ > /tmp/install-docker
- /bin/bash -c "/bin/bash/tmp/install-docker"
- /usr/bin/curl -sSL --retry 12--retry-delay 10https://storage.googleapis.com/kubernetes-release/release/{{{kubectlVersion}}}/bin/linux/amd64/kubectl> /usr/local/bin/kubectl
- chmod +x /usr/local/bin/kubectl
将上面的代码修改为:
runcmd:
- /bin/bash -c "/bin/echoDAEMON_ARGS=--advertise-client-urls""http://127.0.0.1:2379,http://{{{masterPrivateIp}}}:2379""--listen-client-urls ""http://0.0.0.0:2379,http://0.0.0.0:4001""| tee -a /etc/default/etcd"
- /usr/bin/curl -sSL --retry 12--retry-delay 10 http://tiantiaw-sr01.chinacloudapp.cn/install-docker >/tmp/install-docker
- /bin/bash -c "/bin/bash/tmp/install-docker"
- /usr/bin/curl -sSL --retry 12--retry-delay 10 http://tiantiaw-sr01.chinacloudapp.cn/kubectl >/usr/local/bin/kubectl
- chmod +x /usr/local/bin/kubectl
- /usr/bin/docker pull /kubernetes/pause-amd64:3.0
- /usr/bin/docker tag /kubernetes/pause-amd64:3.0gcr.io/google_containers/pause-amd64:3.0
这里的修改主要是将Docker和kubectl的安装路径指向国内的镜像,笔者这里暂时创建了一个nginx服务器,将相关的依赖放到了这里,读者朋友们可以将这些依赖包放到自己的服务器或者CDN上来加快部署过程。
需要留意的一点是kubernetes启动pod的时候需要用到gcr.io/google_containers/pause-amd64这个Docker镜像,我们这里采用一个变通的办法,从友商那里下载一个到kubernetes节点上,然后将它改名成为gcr.io/google_containers/pause-amd64,这样kubernetes的核心服务就都能启动起来了(为了避免广告之嫌,友商名称暂时去掉,感兴趣的朋友可以自行搜索,然后将标红的替换成对应的友商地址就行)。
acs engine的kubernetes集群部署时,需要访问几个Docker镜像,笔者将这些镜像列了出来:
"gcr.io/google_containers/heapster:v1.2.0"
"gcr.io/google_containers/addon-resizer:1.6"
"gcr.io/google_containers/kubedns-amd64:1.7"
"gcr.io/google_containers/kube-dnsmasq-amd64:1.3"
"gcr.io/google_containers/exechealthz-amd64:1.2"
"gcr.io/google_containers/kubernetes-dashboard-amd64:v1.4.2"
"gcr.io/google_containers/kube-addon-manager-amd64:v5.1"
"gcr.io/google_containers/hyperkube-amd64:v1.4.5"
国内访问google是被屏蔽的,所以我们需要将这些镜像替换成国内能够访问的镜像,下面是笔者在友商找到的几个镜像地址(感兴趣的朋友可以根据镜像的名称自行搜索,这里避免广告之嫌就不列出了):
index.xxxcloud.com/google_containers/heapster:v1.2.0-beta.0
index.xxxcloud.com/google_containers/addon-resizer:1.6
index.xxxcloud.com/google_containers/kubedns-amd64:1.7
index.xxxcloud.com/google_containers/kube-dnsmasq-amd64:1.3
index.xxxcloud.com/google_containers/exechealthz-amd64:1.2
index.xxxcloud.com/google_containers/kubernetes-dashboard-amd64:v1.4.2
index.xxxcloud.com/google_containers/kube-addon-manager-amd64:v5.1
index.xxxcloud.com/google_containers/hyperkube-amd64:v1.4.1
具体的替换方式就简单粗暴了,全局搜索对应的以gcr.io开头的镜像,然后替换成国内的镜像就行。
parts目录中的任何修改需要生效的话,必须重新生成一下pkg/acsengine/template.go文件,这个文件是通过go-bindata命令将parts里面的所有脚本片段资源打包到一个文件中,具体的修改方式如下 (假设$ACS_HOME是源码根目录):
进入acs engine源码根目录,执行go build,顺利的话就可以看到acs-engine生成了。
1.登录Azure中国区
azure login –e AzureChinaCloud
2.设置azurecli的模式为arm
azure config mode arm
3.创建资源组(集群中的所有资源都会在这个资源组中创建)
azure group create--name="
4.部署Kubernetes集群
azure group deployment create--name="
5.部署成功后,打开azure门户预览,点选下图中标红的地方,复制masterFQDN。
6.ssh @远程连接到kubernetes master节点
这里的username就是Kubernetes集群描述文件中的adminUsername,masterFQDN就是上图中红色框中的内容。
7.执行kubectl cluster-info, 如果获取到如下的相应,集群就建立成功了
8.执行kubectl get nodes获取集群节点信息
至此为止,我们就在Azure中国区成功部署kubernetes集群了,我们可以尝试在其上部署一个简单的hello world应用,具体的部署过程网上有很多的案例,这里就不赘述了。
Kubernetes的部署过程相对来说比DCOS复杂一点,不仅涉及到国内镜像的问题,还涉及到很多源码的改动,不过修改好源码后,整个部署过程还是很顺利的。通过acs engine可以将以前需要花很长时间才能部署好的kubernetes集群分分钟就部署好,而且还集成了Azure的负责均衡,可以很方便地将Service暴露给外部使用,极大地减轻了IT运维的负担。笔者目前临时使用了几个文件服务器来实现部署,希望不久的将来acs engine能够官方支持Azure中国,这样我们就能更加便利地享受到微软提供的一站式的容器集群解决方案了。