亚马逊AWS官方博客

在 AWS 中国区安装配置 OpenShift

红帽OpenShift是全球领先的企业级Kubernetes容器平台。目前OpenShift拥有大量客户(全球超过1000个),跨越行业垂直市场,并部署大量部署在私有云和公有云上。

图1 OpenShift系统架构图

 

OpenShift早期版本就与AWS进行了集成,也是目前集成最成熟的公有云。尤其在OpenShift 4版本之后,AWS是第一个支持运行OpenShift 4的平台,而且专门为在AWS上部署提供了快速安装的命令行。

本文就针对OpenShift 3.11在AWS中国区的部署进行详细说明,旨在帮助客户在AWS上更好运行OpenShift承载容器化业务。

1. 部署架构说明

在AWS上部署OpenShift 3,可以通过CloudFormation模版快速创建OpenShift所需要的基础设施,并符合AWS的最佳实践,然后通过Ansible部署OpenShift环境。目前在AWS社区已经完全实现了这些功能,Github地址:https://github.com/aws-quickstart/quickstart-redhat-openshift.git,通过提供的CloudFormation模版可以在仅填写少量参数的情况下,就部署一套高可用且自动扩容的OpenShift集群。

不过该方案目前无法在中国区完成创建,在中国区我们需要自行实现OpenShift的部署,最终实现的架构如下图所示:

图2 OpenShift3在AWS上的部署架构图

 

从图中可以看出OpenShift3在AWS上的高可用架构。为了保证3 AZ,优先选择宁夏区建设,三个Master节点和Etcd节点共用实例,创建至少三个Infra节点保证路由器的高可用,计算节点根据需要添加即可。另外,由于国内下载镜像和RPM的速度较慢,建议提前同步好,并存放在Ansible Server上搭建私服。

我们接下来就在中国区完成OpenShift 3的部署。

2. 环境初始化

本小节描述需要准备的AWS基础设施,包括网络、EC2、ELB等,主要包含如下:

  • 一个虚拟私有网络(VPC):VPC将分布在三个AZ中,在每个AZ中分别创建一个私有子网和公有的子网。
  • Internet Gateway为VPC提供公网访问。Private Subnet的实例先经过NAT Gateway,再到Internet Gateway访问公网,而Public Subnet的实例直接经过Internet Gateway访问公网。
  • 部署OpenShift的Ansible Server运行在一个AZ的Public Subnet中。
  • 在每个私有子网中,将包含一个Master节点,一个ETCD节点,一定数量的Node节点。Node节点按运行服务可分为infra节点和app节点。
  • 所有的OpenShift节点按角色放置在对应的AutoScaling Group中。Master节点和ETCD节点的AutoScaling Group的实例数是固定的,不允许自动扩容。默认均为3个,每个AZ运行一个实例,这样做的目的是确保如果有Master或ETCD节点出现故障,AutoScaling Group会自动替换故障的节点。Node节点的初始数目自行配置,会根据配置的数目自动散布在三个AZ中。
  • 三个Master节点和多个Infra节点分别使用ELB提供负载均衡。

为了读者更清楚了解整个过程,我们简要说明手动创建的过程,当然,你可以使用任何的自动化工具实现。

首先,你需要登陆AWS中国区,切换到宁夏Region。

2.1 网络环境的创建

主要包含VPC,子网等网络资源。

  • 创建独立运行OpenShift的VPC,设置网段为10.0.0.0/16,开启dns和hostname。添加tag为kubernetes.io/cluster/${CLUSTER_NAME},Value=shared。其中${CLUSTER_NAME}为自定义的OpenShift集群名称。
  • 创建Internet Gateway,并分配到新建的VPC上。
  • 创建一个公网路由表,并设置路由规则,目的地0.0.0.0/0,目标为新建的Internet Gateway。
  • 在每个可用区创建一个Public Subnet,子网掩码设置为/20,并将新建的公网路由表绑定在所有的Public Subnet上;修改Public Subnet的属性,允许启动分配公网IP。
  • 所有的Public Subnet添加tag为kubernetes.io/cluster/${CLUSTER_NAME},Value=owned。其中${CLUSTER_NAME}与VPC上设置的名称保持一致。
  • 创建与可用区相同数目的EIP,宁夏区为3个。
  • 在每个可用区的Public Subnet中创建一个NAT Gateway,并分别绑定一个EIP。
  • 在每个可用区创建一个私网路由表,并设置路由规则,目的地0.0.0.0/0,目标为每个可用区对应的NAT Gateway。
  • 在每个可用区创建一个Private Subnet,子网掩码设置为/20,并将每个可用区新建的私网路由表添加绑定在对应可用区的Private Subnet上。
  • 所有的Private Subnet添加tag为kubernetes.io/cluster/${CLUSTER_NAME},Value=owned。其中${CLUSTER_NAME}与VPC上设置的保持一致。

2.2 IAM Role的创建

主要包含Master节点和Node节点需要的权限,创建名为OCP-Setuprole的Role,添加内连Policy,内容如下:

 

{

    "Version": "2012-10-17",

    "Statement": [

        {

            "Action": [

                "ec2:DescribeVolume*",

                "ec2:CreateVolume",

                "ec2:CreateTags",

                "ec2:DescribeInstances",

                "ec2:AttachVolume",

                "ec2:DetachVolume",

                "ec2:DeleteVolume",

                "ec2:DescribeSubnets",

                "ec2:CreateSecurityGroup",

                "ec2:DescribeSecurityGroups",

                "ec2:DescribeRouteTables",

                "ec2:AuthorizeSecurityGroupIngress",

                "ec2:RevokeSecurityGroupIngress",

                "elasticloadbalancing:DescribeTags",

                "elasticloadbalancing:CreateLoadBalancerListeners",

                "elasticloadbalancing:ConfigureHealthCheck",

                "elasticloadbalancing:DeleteLoadBalancerListeners",

                "elasticloadbalancing:RegisterInstancesWithLoadBalancer",

                "elasticloadbalancing:DescribeLoadBalancers",

                "elasticloadbalancing:CreateLoadBalancer",

                "elasticloadbalancing:DeleteLoadBalancer",

                "elasticloadbalancing:ModifyLoadBalancerAttributes",

                "elasticloadbalancing:DescribeLoadBalancerAttributes"

            ],

            "Resource": "*",

            "Effect": "Allow",

            "Sid": "1"

        }   

    ]

}

2.3 创建Ansible Server的EC2实例

在Public Subnet中创建一个EC2实例,用于安装Ansible,并作为SSH的跳板机。

  • 在宁夏Region ,创建SSH keypair,当然可以选择使用已经存在的。
  • 创建安全组,名称为ansible-server-sg,安全组入口规则,允许TCP:22,源为0.0.0.0/0。
  • 在第一个可用区的Public Subnet中,创建一个6操作系统的EC2实例,磁盘设置为100G,安全组设置为新建的ansible-server-sg。

2.4 创建Master节点的EC2实例

分别在三个私有子网中创建一个实例作为Master节点和ETCD节点。

  • 创建Master节点的安全组,名称为ocp-master-sg。在安全组中添加入口规则:
  • 允许TCP:22,源为VPC的地址端10.0.0.0/16。
  • 允许all:all,源为VPC的地址端10.0.0.0/16。
  • 在新建的Master节点安全组添加标签:kubernetes.io/cluster/${CLUSTER_NAME},Value=owned。
  • 选择任意一个Private Subnet创建一个Master节点,操作系统选择6,实例类型选择t2.xlarge,选择IAM Role为OCP-Setuprole,磁盘设置为100GB,安全组选择新建的Master节点安全组ocp-master-sg,SSH Key建议和跳板机选择的一致。
  • 在新建的Master节点上添加标签:kubernetes.io/cluster/${CLUSTER_NAME},Value=owned

2.5 创建Node节点的EC2实例

分别在私有子网中创建3个实例作为Infra节点和计算节点。

  • 创建Node节点的安全组,名称为ocp-node-sg。在安全组中添加入口规则:
  • 允许TCP:22,源为VPC的地址端10.0.0.0/16。
  • 允许all:all,源为VPC的地址端10.0.0.0/16。
  • 允许TCP:30000-32767,源为0.0.0.0/16。
  • 在新建的Node节点安全组添加标签:kubernetes.io/cluster/${CLUSTER_NAME},Value=owned。
  • 分别在三个Private Subnet创建一个Node节点,操作系统选择6,实例类型选择t2.2xlarge,选择IAM Role为OCP-Setuprole,磁盘设置为100GB,安全组选择新建的Node节点安全组ocp-node-sg,SSH Key建议和跳板机选择的一致。
  • 在新建的三个Node节点上添加标签:kubernetes.io/cluster/${CLUSTER_NAME},Value=owned

2.6 创建Master LB

在安装之前需要创建一个Master LB提供master API的访问,同时该地址也是OpenShift Console访问的URL。这里我们直接使用Internet类型的ELB实现。

  • 创建Master负载均衡的安全组,名称为ocp-masterlb-sg。在安全组中添加入口规则:
  • 允许TCP:8443,源为VPC的地址端0.0.0.0/0。
  • 允许all:all,源为VPC的地址端10.0.0.0/16。
  • 在EC2界面创建Load Balancers,类型选择ELB,名称设置为ocp-master-lb,VPC选择为OpenShift的VPC,监听8443端口,subnet选择三个AZ的Public Subnet,配置安全组为新建的ocp-masterlb-sg,注册三个Master节点的EC2实例。

到此为止,安装OpenShift3所需要的AWS基础设施就创建完成了。

3. 部署OpenShift3

创建好部署OpenShift所需要的基础设施,我们就可以开始执行OpenShift部署了。由于只有Ansible Server分配有公网IP,这也将作为我们的跳板机。

3.1 操作系统初始化

在这个阶段完成所有安装OpenShift之前的操作系统初始化,在所有节点完成以下配置。

1)配置Hostname

在公有云使用EC2实例的私有DNS名称作为节点名称,建议不要修改,否则安装过程可能会出错。

2)开启Selinux:保持Selinux为非disable状态。

    # setenforce 0

    # sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

3)关闭Firewalld

关闭操作系统防火墙Firewalld

    # systemctl stop firewalld

    # systemctl mask firewalld

4)关闭节点SWAP

    # swapoff -a

3.2 配置Yum源

由于国内下载速度较慢,建议提前从海外同步RPM包。需要同步的RPM包频道如下:

  • rhel-7-server-rpms
  • rhel-7-server-extras-rpms
  • rhel-7-server-ose-3.11-rpms
  • rhel-7-server-ansible-2.6-rpms

同步完成后,在Ansible-Server上安装HTTP建设YUM源,步骤比较简单不在赘述。YUM Server配置完成后,需要配置所有节点使用搭建的私有YUM源安装软件包。

注意:在配置Yum Server完成后,需要更新Ansible Server所关联的安全组,开启相应的端口。

3.3 外部镜像仓库

在OpenShift安装过程中,需要多个系统组件的Docker镜像。我们可以使用AWS服务ECR(Elastic Contriner Registry),也可以使用自建的镜像仓库存放这些镜像。如果自建镜像仓库,建议选择S3作为后端存储,使得仓库更具有弹性和高可用性。

注意:如果选择使用Ansible Server自建镜像仓库,需要更新Ansible Server所关联的安全组,开启相应的端口。

3.4 Openshift安装前准备

3.4.1 安装必要的基础软件包

在所有的OpenShift Master节点和Node节点上安装软件包并配置基础环境。在所有OpenShift节点上安装OpenShift需要的软件包,命令如下:

# yum -y install wget git net-tools bind-utils iptables-services bridge-utils bash-completion vim atomic-openshift-excluder atomic-openshift-docker-excluder unzip

# yum -y update

# atomic-openshift-excluder unexcluded

3.4.2 安装配置Docker

在所有OpenShift Master节点和Node节点上安装Docker。命令如下:

# yum install -y docker

如果还需要修改docker配置文件,如添加非安全的镜像仓库、修改docker0桥的地址等,则在启动docker服务前进行。

启动docker进程并开机自启

# systemctl start docker

# systemctl enable docker

如果需要为Docker配置独立的存储,请参考OpenShift官方文档,本文不在赘述。

3.4.3 安装和配置Ansible主控节点

OpenShift 3使用Ansible完成自动化安装,关于Ansible的介绍和使用请参考官方文档

在Ansible Server节点安装ansible和用于安装OpenShift的playbook

# yum -y install openshift-ansible

使用Ansible需要通过SSH连接到被控节点,可以配置SSH免密登录。

在Ansible节点上生成SSH公私钥。命令如下,应答输入请直接输入回车。

# ssh-keygen

在Ansible节点上配置到所有节点的SSH主机互信。命令如下,请根据提示输入远程主机root账户密码。

# ssh-copy-id root@<hostname或ip>

3.5 配置Ansible Inventory

在所有的准备工作完成后,我们只需要登录Ansible Server控制机,修改Inventory之后运行Ansible Playbook即可。

提供的Inventory示例如下:

#Create an OSEv3 group that contains the masters, nodes, and etcd groups
[OSEv3:children]
masters
nodes
etcd

# Set variables common for all OSEv3 hosts
[OSEv3:vars]
# SSH user, this user should allow ssh based auth without requiring a password
# ansible_ssh_user=ec2-user

# If ansible_ssh_user is not root, ansible_become must be set to true
# ansible_become=true

openshift_deployment_type=openshift-enterprise
openshift_image_tag=v3.11.59
openshift_pkg_version=-3.11.59
openshift_clock_enabled=true

openshift_clusterid=${CLUSTER_NAME}
openshift_cloudprovider_kind=aws

openshift_hosted_router_replicas=2
openshift_router_selector='router_node=true'
openshift_hosted_registry_replicas=2
openshift_registry_selector='registry_node=true'


openshift_master_cluster_method=native
openshift_master_cluster_hostname=${MASTER_INTERNAL_LB_DNS}
openshift_master_cluster_public_hostname=${MASTER_INTERNET_LB_DNS}
openshift_master_default_subdomain=${CLUSTER_SUBDOMAIN}
openshift_docker_options="--selinux-enabled --insecure-registry 172.30.0.0/16 --log-driver json-file --log-opt max-size=50M --log-opt max-file=3"

oreg_url=${REGISTRY_URL}/openshift3/ose-${component}:${version}
openshift_examples_modify_imagestreams=true

#install andon later
openshift_metrics_install_metrics=false
openshift_enable_service_catalog=false
ansible_service_broker_install=false
openshift_cluster_monitoring_operator_install=false
openshift_logging_install_logging=false


#set cert expire days
openshift_ca_cert_expire_days=3600
openshift_node_cert_expire_days=3600
openshift_master_cert_expire_days=3600


# uncomment the following to enable htpasswd authentication; defaults to DenyAllPasswordIdentityProvider
openshift_master_identity_providers=[{'name': 'htpasswd_auth', 'login': 'true', 'challenge': 'true', 'kind': 'HTPasswdPasswordIdentityProvider'}]

openshift_disable_check="disk_availability,docker_image_availability,memory_availability,docker_storage,package_version"

openshift_node_groups=[{'name': 'node-config-master', 'labels': ['node-role.kubernetes.io/master=true']}, {'name': 'node-config-compute-infra', 'labels': ['node-role.kubernetes.io/infra=true', 'node-role.kubernetes.io/compute=true', 'registry_node=true', 'router_node=true']}, {'name': 'node-config-compute', 'labels': ['node-role.kubernetes.io/compute=true']}, {'name': 'node-config-infra', 'labels': ['node-role.kubernetes.io/infra=true', 'registry_node=true', 'router_node=true']}]

# host group for masters
[masters]
ip-xxx1.cn-northwest-1.compute.internal
ip-xxx2.cn-northwest-1.compute.internal
ip-xxx3.cn-northwest-1.compute.internal

# host group for etcd
[etcd]
ip-xxx1.cn-northwest-1.compute.internal
ip-xxx2.cn-northwest-1.compute.internal
ip-xxx3.cn-northwest-1.compute.internal

# host group for nodes, includes region info
[nodes]
ip-xxx1.cn-northwest-1.compute.internal openshift_node_group_name='node-config-master'
ip-xxx2.cn-northwest-1.compute.internal openshift_node_group_name='node-config-master'
ip-xxx3.cn-northwest-1.compute.internal openshift_node_group_name='node-config-master'
ip-xxx4.cn-northwest-1.compute.internal openshift_node_group_name='node-config-infra-compute'
ip-xxx5.cn-northwest-1.compute.internal openshift_node_group_name='node-config-infra-compute'
ip-xxx6.cn-northwest-1.compute.internal openshift_node_group_name='node-config-compute'

注意:示例文件中${}的变量需要根据实际环境修改。

下面我们对部分重要的配置进行说明。

  • 与AWS集成配置

OpenShift需要与底层AWS的服务进行交互,使用一些AWS资源或获取信息,如挂载EBS卷,这就需要在Ansible Inventory中配置集成的相关信息。我们推荐使用IAM Role认证,这种方式更加安全。仅需在Ansible Inventory添加以下参数:

openshift_clusterid=${CLUSTER_NAME}

openshift_cloudprovider_kind=aws
  • 负载均衡ELB

openshift_master_cluster_method=native

openshift_master_cluster_hostname=${MASTER_INTERNAL_LB_DNS}

openshift_master_cluster_public_hostname=${MASTER_INTERNET_LB_DNS}

openshift_master_default_subdomain=${CLUSTER_SUBDOMAIN}

其中openshift_master_cluster_method表示使用高可用的方式部署;openshift_master_cluster_hostname表示创建的用于内部访问Master API的ELB DNS名称;openshift_master_cluster_public_hostname表示创建的用于外部访问Master API的ELB DNS名称。在示例中,我们仅创建了一个Internet类型的ELB,上述两个参数均设置为同一个ELB的DNS名称;openshift_master_default_subdomain表示OpenShift中创建Route默认的域名,如设定为apps.awscloud.com。

  • 镜像仓库地址

oreg_url=${REGISTRY_URL}/openshift3/ose-${component}:${version}

其中oreg_url表示外部镜像仓库的地址,根据实际环境修改此参数,默认使用registry.access.redhat.com。

3.6 执行安装脚本

Ansible Inventory配置完成后运行playbook执行安装,

安装前测试节点连通性

# ansible -m ping all

执行安装:

# cd /usr/share/ansible/openshift-ansible

# ansible-playbook -vv playbooks/prerequisites.yml

# ansible-playbook -vv playbooks/deploy_cluster.yml

如果安装过程中遇到问题,查明原因之后,执行如下卸载命令之后再次执行安装命令

# ansible-playbook playbooks/adhoc/uninstall.yml

安装完成后通过执行如下命令执行检测集群状态。

  • 执行oc get node可以查看集群节点的情况。
  • 执行oc get pod –all-namespaces检测集群所有容器是否运行正常。

4.  安装后配置和测试

4.1 添加管理员用户

在集群安装完成后,需要添加用户才能登陆使用OpenShift。OpenShift支持集成多种用户认证系统,如LDAP、Github等。在本示例中,我们使用HTPasswdPasswordIdentityProvider的认证方式。

添加管理员用户admin,并设置密码为admin,赋予集群管理员权限。分别在三个master节点上执行如下命令:

# htpasswd -bc /etc/origin/master/htpasswd admin admin

然后在任意一个Master节点执行以下命令完成admin赋权

# oc adm policy add-cluster-role-to-user cluster-admin admin

4.2 安装监控组件

在初次安装的时候,建议无需把所有组件一次性安装。我们可以后续逐个安装,降低安装失败的风险。

在Ansible Server节点执行操作。

修改ansible inventory,调整监控参数为true

openshift_metrics_install_metrics=false

运行安装playbook

# ansible-playook /usr/share/ansible/openshift-ansible/playbooks/byo/openshift-cluster/openshift-metrics.yml

运行完成之后检查pod的状态

# oc project openshift-infra

# oc get pods

4.3 安装Prometheus监控

在Ansible Server节点执行操作。

修改ansible inventory,调整prometheus参数为true

openshift_cluster_monitoring_operator_install=true

运行安装playbook

# ansible-playook /usr/share/ansible/openshift-ansible/playbooks/byo/openshift-monitoring/config.yml

部署完成之后,确认所有相关的pod正确启动。

# oc project openshift-monitoring

# oc get pods

4.4 安装日志组件

在Ansible Server节点执行操作。

修改ansible inventory,调整日志参数为true

openshift_logging_install_logging=true

openshift_logging_es_nodeselector={“node-role.kubernetes.io/infra”:”true”}

运行安装playbook

# cd /usr/share/ansible/openshift-ansible/

# ansible-playbook -vv playbooks/byo/openshift-cluster/openshift-logging.yml

到此为止,所有的安装工作就结束了,我们可以访问https://<MASTER_LB_DNS>:8443体验OpenShift了。

注意:中国区在公网访问8443端口需要备案。

 

访问的OpenShift界面如下图所示:

图3 OpenShift访问界面图

 

5. 结语

值得一提的是,在安装过程中,默认会创建名为gp2的StorageClass,可以在集群中直接创建PVC动态申请EBS卷使用。

OpenShift运行在AWS上的集成不仅仅于此,更具魔法的功能是可以通过Service Catalog直接在OpenShift为应用启动AWS原生服务,如S3.这样运行在OpenShift中的容器应用可以直接使用AWS的服务,为业务带来更快的创新速度。关于在中国区如何利用Service Catalog实现OpenShift调用AWS服务的功能,我们将在下一篇博客中揭晓,敬请期待。

 

本篇作者

郭跃军

亚马逊 AWS 专业服务团队云架构咨询顾问。擅长PaaS 建设运维、 DevOps 以及微服务改造迁移等有丰富的经验。负责企业级客户的云架构设计和优化、云上自动化运维、容器化平台设计咨询等,对云原生技术有深入的研究和热情。