Openshift高阶探索实验

时间:2022-05-05
本文章向大家介绍Openshift高阶探索实验,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

一、HA方式部署Openshift

一个典型的OCP高可用架构是:master至少应为三个,且为奇数个(上面有etcd);

基础架构节点不少于两个,上面运行日志、监控、router、INTEGRATED REGISTRY。

Openshift的计算节点不少于2个,以保证当一个节点出现故障的时候,不影响应用。

在Openshift中,两个重要的流量入口组件是Master和Router。

在生产环境中,为了保证高可用,Master和Router都会配置多个。这就引入了一个问题:多个Master和Router对外如何提供统一的域名。

这时候,需要使用客户数据中心/公有云的负载均衡。当然,在数据中心内,我们也可以通过Haproxy搭建软负载,这和使用F5的设备无本质区别。

在考虑流量入口的负载均衡的同时,我们还需要考虑DNS的问题。当然,商业的F5通常有DNS的功能。

针对Master,多个Master会有一个VIP/域名。VIP和多个Master都需要被DNS解析。在负载均衡器上,将Master VIP的域名(如master.ocp.example.com)和多个Master的域名对应起来,同时设置负载均衡策略,如roundrobin等。

针对Router, DNS需要将应用对外的域名,解析成router所在的openshift节点的域名。如果有多个router,就需要个多个router配置VIP和它的域名。VIP被解析成多个router所在的Openshift节点的域名(同时配置负载均衡策略)。而DNS上进行配置,对应用对泛域名解析,将其解析成router的VIP。

在Openshift中,etcd做服务发现,其K-V数据库存放Openshift的信息。

为了保证etcd的高可用,在生产环境中,etcd应配置成奇数个(2n+1),并且每个etcd成员之间的网络延迟小于5ms。

在Openshift中,建议将etcd与Master节点部署到一起。也就是三个master上,每个master上一个etcd。

目前Openshift的日志使用EFK,具体概念不展开讲,请参照其他文档。

在EFK中,Elasticsearch需要高可用,和etcd一样,需要2n+1个节点,以保证高可用并规避脑裂。

在Openshift的监控数据中,Cassandra分布式数据库存放监控信息,因此需要做高可用。在多个Cassandra之间,做存储的复制。

在Openshift中,集成镜像仓库通常用于存放dev成功后的镜像,以完成整个CI/CD过程。他与数据中心外部镜像仓库是分开的,作用也不一样。

在生产环境中,INTEGRATED REGISTRY通常会被配置成多个。

同样,需要给多个REGISTRY配置VIP和域名。多个REGISTRY的VIP通过负载均衡器的roundrbin指向多个registery。

在本实验中,Openshift的架构如下:

首先登录到管理节点,编辑/etc/ansible/hosts,内容如下(需要注意的是:下面内容用于ansible安装整套环境,使用的是节点的内部名称,而非上面列出的public FQDN):

安装的时候,网络模式选择openshift-ovs-multitenant。

cat /etc/ansible/hosts

[OSEv3:vars]

###########################################################################

### Ansible Vars

###########################################################################

timeout=60

ansible_become=yes

ansible_ssh_user=ec2-user

###########################################################################

### OpenShift Basic Vars

###########################################################################

deployment_type=openshift-enterprise

containerized=false

openshift_disable_check="disk_availability,memory_availability"

# default project node selector

osm_default_node_selector='env=app'

# Configure node kubelet arguments. pods-per-core is valid in OpenShift Origin 1.3 or OpenShift Container Platform 3.3 and later.

openshift_node_kubelet_args={'pods-per-core': ['10'], 'max-pods': ['250'], 'image-gc-high-threshold': ['85'], 'image-gc-low-threshold': ['75']}

# Configure logrotate scripts

# See: https://github.com/nickhammond/ansible-logrotate

logrotate_scripts=[{"name": "syslog", "path": "/var/log/cronn/var/log/maillogn/var/log/messagesn/var/log/securen/var/log/spoolern", "options": ["daily", "rotate 7","size 500M", "compress", "sharedscripts", "missingok"], "scripts": {"postrotate": "/bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true"}}]

###########################################################################

### OpenShift Optional Vars

###########################################################################

# Enable cockpit

osm_use_cockpit=true

osm_cockpit_plugins=['cockpit-kubernetes']

###########################################################################

### OpenShift Master Vars

###########################################################################

openshift_master_api_port=443

openshift_master_console_port=443

openshift_master_cluster_method=native

openshift_master_cluster_hostname=loadbalancer.db84.example.opentlc.com

openshift_master_cluster_public_hostname=loadbalancer.db84.example.opentlc.com

openshift_master_default_subdomain=apps.db84.example.opentlc.com

openshift_master_overwrite_named_certificates=True

openshift_master_ca_certificate={'certfile': '/root/intermediate_ca.crt', 'keyfile': '/root/intermediate_ca.key'}

openshift_set_hostname=True

###########################################################################

### OpenShift Network Vars

###########################################################################

osm_cluster_network_cidr=10.1.0.0/16

openshift_portal_net=172.30.0.0/16

os_sdn_network_plugin_name='redhat/openshift-ovs-multitenant'

#os_sdn_network_plugin_name='redhat/openshift-ovs-subnet'

# This should be turned on once all dependent scripts use firewalld rather than iptables

# os_firewall_use_firewalld=True

###########################################################################

### OpenShift Authentication Vars

###########################################################################

# htpasswd auth

openshift_master_identity_providers=[{'name': 'htpasswd_auth', 'login': 'true', 'challenge': 'true', 'kind': 'HTPasswdPasswordIdentityProvider', 'filename': '/etc/origin/master/htpasswd'}]

# Defining htpasswd users

#openshift_master_htpasswd_users={'user1': '<pre-hashed password>', 'user2': '<pre-hashed password>'}

# or

openshift_master_htpasswd_file=/root/htpasswd.openshift

###########################################################################

### OpenShift Metrics and Logging Vars

###########################################################################

# Enable cluster metrics

openshift_metrics_install_metrics=True

openshift_metrics_storage_kind=nfs

openshift_metrics_storage_access_modes=['ReadWriteOnce']

openshift_metrics_storage_nfs_directory=/srv/nfs

openshift_metrics_storage_nfs_options='*(rw,root_squash)'

openshift_metrics_storage_volume_name=metrics

openshift_metrics_storage_volume_size=10Gi

openshift_metrics_storage_labels={'storage': 'metrics'}

#openshift_master_metrics_public_url=https://hawkular-metrics.apps.db84.example.opentlc.com/hawkular/metrics

## Add Prometheus Metrics:

openshift_hosted_prometheus_deploy=true

openshift_prometheus_node_selector={"env":"infra"}

openshift_prometheus_namespace=openshift-metrics

# Prometheus

openshift_prometheus_storage_kind=nfs

openshift_prometheus_storage_access_modes=['ReadWriteOnce']

openshift_prometheus_storage_nfs_directory=/srv/nfs

openshift_prometheus_storage_nfs_options='*(rw,root_squash)'

openshift_prometheus_storage_volume_name=prometheus

openshift_prometheus_storage_volume_size=10Gi

openshift_prometheus_storage_labels={'storage': 'prometheus'}

openshift_prometheus_storage_type='pvc'

# For prometheus-alertmanager

openshift_prometheus_alertmanager_storage_kind=nfs

openshift_prometheus_alertmanager_storage_access_modes=['ReadWriteOnce']

openshift_prometheus_alertmanager_storage_nfs_directory=/srv/nfs

openshift_prometheus_alertmanager_storage_nfs_options='*(rw,root_squash)'

openshift_prometheus_alertmanager_storage_volume_name=prometheus-alertmanager

openshift_prometheus_alertmanager_storage_volume_size=10Gi

openshift_prometheus_alertmanager_storage_labels={'storage': 'prometheus-alertmanager'}

openshift_prometheus_alertmanager_storage_type='pvc'

# For prometheus-alertbuffer

openshift_prometheus_alertbuffer_storage_kind=nfs

openshift_prometheus_alertbuffer_storage_access_modes=['ReadWriteOnce']

openshift_prometheus_alertbuffer_storage_nfs_directory=/srv/nfs

openshift_prometheus_alertbuffer_storage_nfs_options='*(rw,root_squash)'

openshift_prometheus_alertbuffer_storage_volume_name=prometheus-alertbuffer

openshift_prometheus_alertbuffer_storage_volume_size=10Gi

openshift_prometheus_alertbuffer_storage_labels={'storage': 'prometheus-alertbuffer'}

openshift_prometheus_alertbuffer_storage_type='pvc'

openshift_metrics_cassandra_nodeselector={"env":"infra"}

openshift_metrics_hawkular_nodeselector={"env":"infra"}

openshift_metrics_heapster_nodeselector={"env":"infra"}

# Enable cluster logging

openshift_logging_install_logging=True

openshift_logging_storage_kind=nfs

openshift_logging_storage_access_modes=['ReadWriteOnce']

openshift_logging_storage_nfs_directory=/srv/nfs

openshift_logging_storage_nfs_options='*(rw,root_squash)'

openshift_logging_storage_volume_name=logging

openshift_logging_storage_volume_size=10Gi

openshift_logging_storage_labels={'storage': 'logging'}

# openshift_logging_kibana_hostname=kibana.apps.db84.example.opentlc.com

openshift_logging_es_cluster_size=1

openshift_logging_es_nodeselector={"env":"infra"}

openshift_logging_kibana_nodeselector={"env":"infra"}

openshift_logging_curator_nodeselector={"env":"infra"}

###########################################################################

### OpenShift Project Management Vars

###########################################################################

# Configure additional projects

openshift_additional_projects={'my-infra-project-test': {'default_node_selector': 'env=infra'}}

###########################################################################

### OpenShift Router and Registry Vars

###########################################################################

openshift_hosted_router_selector='env=infra'

openshift_hosted_router_replicas=2

#openshift_hosted_router_certificate={"certfile": "/path/to/router.crt", "keyfile": "/path/to/router.key", "cafile": "/path/to/router-ca.crt"}

openshift_hosted_registry_selector='env=infra'

openshift_hosted_registry_replicas=1

openshift_hosted_registry_storage_kind=nfs

openshift_hosted_registry_storage_access_modes=['ReadWriteMany']

openshift_hosted_registry_storage_nfs_directory=/srv/nfs

openshift_hosted_registry_storage_nfs_options='*(rw,root_squash)'

openshift_hosted_registry_storage_volume_name=registry

openshift_hosted_registry_storage_volume_size=20Gi

openshift_hosted_registry_pullthrough=true

openshift_hosted_registry_acceptschema2=true

openshift_hosted_registry_enforcequota=true

###########################################################################

### OpenShift Service Catalog Vars

###########################################################################

openshift_enable_service_catalog=true

template_service_broker_install=true

openshift_template_service_broker_namespaces=['openshift']

openshift_hosted_etcd_storage_kind=nfs

openshift_hosted_etcd_storage_nfs_options="*(rw,root_squash,sync,no_wdelay)"

openshift_hosted_etcd_storage_nfs_directory=/srv/nfs

openshift_hosted_etcd_storage_volume_name=etcd-vol2

openshift_hosted_etcd_storage_access_modes=["ReadWriteOnce"]

openshift_hosted_etcd_storage_volume_size=5G

openshift_hosted_etcd_storage_labels={'storage': 'etcd'}

###########################################################################

### OpenShift Hosts

###########################################################################

[OSEv3:children]

lb

masters

etcd

nodes

nfs

[lb]

loadbalancer1.db84.internal host_zone=eu-central-1b

[masters]

master3.db84.internal host_zone=eu-central-1b

master1.db84.internal host_zone=eu-central-1b

master2.db84.internal host_zone=eu-central-1b

[etcd]

master3.db84.internal host_zone=eu-central-1b

master1.db84.internal host_zone=eu-central-1b

master2.db84.internal host_zone=eu-central-1b

[nodes]

## These are the masters

master3.db84.internal openshift_hostname=master3.db84.internal openshift_node_labels="{'logging':'true','openshift_schedulable':'False','cluster': 'db84', 'zone': 'eu-central-1b'}"

master1.db84.internal openshift_hostname=master1.db84.internal openshift_node_labels="{'logging':'true','openshift_schedulable':'False','cluster': 'db84', 'zone': 'eu-central-1b'}"

master2.db84.internal openshift_hostname=master2.db84.internal openshift_node_labels="{'logging':'true','openshift_schedulable':'False','cluster': 'db84', 'zone': 'eu-central-1b'}"

## These are infranodes

infranode1.db84.internal openshift_hostname=infranode1.db84.internal openshift_node_labels="{'logging':'true','cluster': 'db84', 'env':'infra', 'zone': 'eu-central-1b'}"

infranode2.db84.internal openshift_hostname=infranode2.db84.internal openshift_node_labels="{'logging':'true','cluster': 'db84', 'env':'infra', 'zone': 'eu-central-1b'}"

## These are regular nodes

node2.db84.internal openshift_hostname=node2.db84.internal openshift_node_labels="{'logging':'true','cluster': 'db84', 'env':'app', 'zone': 'eu-central-1b'}"

node1.db84.internal openshift_hostname=node1.db84.internal openshift_node_labels="{'logging':'true','cluster': 'db84', 'env':'app', 'zone': 'eu-central-1b'}"

[nfs]

support1.db84.internal openshift_hostname=support1.db84.internal

接下来,确认所有节点都可以访问:

#sudo ansible all -m ping

确认OCP集群中的节点Docker都已经安装并启动。

ansible all -m shell -a"systemctl status docker"

确认NFS server配置正确:

查看repo:

通过ansible的方式,在管理节点上部署OCP.

首先下载证书:

wget http://ipa.shared.example.opentlc.com/ipa/config/ca.crt -O /root/ipa-ca.crt

这个证书会与实验环境中的IDM进行认证。

获取用于签署OpenShift系统中所有密钥的“中介CA”密钥和证书。

# wget http://admin.na.shared.opentlc.com/certificates/intermediate.cert.pem -O /root/intermediate_ca.crt

# wget http://admin.na.shared.opentlc.com/certificates/intermediate.key.pem -O /root/intermediate_ca.key

接下来,执行ansible-playbook安装OCP:

#ansible-playbook -f 20 /usr/share/ansible/openshift-ansible/playbooks/byo/config.yml

查看节点,都安装成功:

检查证书是否已经部署到master上:

已经部署成功。

查看master节点上的证书:

ansible masters -m shell -a 'for x in $(ls /etc/origin/master/*.crt); do echo $x; openssl x509 -subject -issuer -in ${x} -noout; echo; done' | less

查看node上的证书:

ansible nodes -m shell -a 'for x in $(ls /etc/origin/node/*.crt); do

echo $x; openssl x509 -subject -issuer -in ${x} -noout; echo;done' | less

OCP安装成功以后,访问master是通过访问loadbalance实现的:

接下来,在NFS server上创建目录,这将作为后续PV使用:

mkdir -p /srv/nfs/user-vols/pv{1..200}

for pvnum in {1..50} ; do

echo /srv/nfs/user-vols/pv${pvnum} *(rw,root_squash) >> /etc/exports.d/openshift-uservols.exports

chown -R nfsnobody.nfsnobody /srv/nfs

chmod -R 777 /srv/nfs

done

systemctl restart nfs-server

在master1上创建25个每个5G大小PV的配置文件:

export GUID=`hostname|awk -F. '{print $2}'`
echo $GUID
export volsize="5Gi"
mkdir /root/pvs
for volume in pv{1..25} ; do
cat << EOF > /root/pvs/${volume}
{
  "apiVersion": "v1",
  "kind": "PersistentVolume",
  "metadata": {
    "name": "${volume}"
  },
  "spec": {
    "capacity": {
        "storage": "${volsize}"
    },
    "accessModes": [ "ReadWriteOnce" ],
    "nfs": {
        "path": "/srv/nfs/user-vols/${volume}",
        "server": "support1.${GUID}.internal"
    },
    "persistentVolumeReclaimPolicy": "Recycle"
  }
}
EOF
echo "Created def file for ${volume}";
done;
在master1上创建25个每个10G大小PV的配置文件:
export volsize="10Gi"
for volume in pv{26..50} ; do
cat << EOF > /root/pvs/${volume}
{
  "apiVersion": "v1",
  "kind": "PersistentVolume",
  "metadata": {
    "name": "${volume}"
  },
  "spec": {
    "capacity": {
        "storage": "${volsize}"
    },
    "accessModes": [ "ReadWriteMany" ],
    "nfs": {
        "path": "/srv/nfs/user-vols/${volume}",
        "server": "support1.${GUID}.internal"
    },
    "persistentVolumeReclaimPolicy": "Retain"
  }
}
EOF
echo "Created def file for ${volume}";
done;

最后,创建pv:

cat pvs/* | oc create -f -

二、Openshift SDN多租户模式探究

OCP的安装使用的是多租户的模式。

我们查看project,可以看到NetID:

接下来,创建两个项目并在项目中部署应用:

oc new-project pizzaparty-dev

oc new-project fancypants-dev

oc new-app openshift/hello-openshift:v1.1.1.1 -n pizzaparty-dev

oc new-app openshift/hello-openshift:v1.1.1.1 -n fancypants-dev

查看pod:

在两个项目中各创建一个起bash的pod:

查看项目的netid:

接下来,我们看一下新创建的两个项目之间是否是相互隔离的。

先找出两个项目中的两个pod的IP:

我们登录第一个项目的shelly pod:

先访问非本项目的pod,失败:

访问本项目的pod:

这说明ovs的多租户模式,使项目之间的网络隔离。

接下来,我们对两个项目做join操作:

oadm pod-network join-projects --to=fancypants-dev pizzaparty-dev

然后再进行测试,不同项目之间的网络已经打通:

三、Openshift SDN Service Layer探究

创建一个新的项目,并部署一个应用:

#oc new-project servicelayer

# oc new-app openshift/hello-openshift

将pod副本扩展为4:

oc scale dc/hello-openshift --replicas=4

查看刚创建应用的service layer:

oc describe service hello-openshift

可以看到service ip是172.30.198.53。

查看iptabls上80端口对于本应用的规则:

iptables-save | grep servicelayer/hello-openshift | grep 8080 |grep -i 172.30.198.53

-A KUBE-SERVICES -d 172.30.198.53/32 -p tcp -m comment --comment "servicelayer/hello-openshift:8080-tcp cluster IP" -m tcp --dport 8080 -j KUBE-SVC-BXIL3WE3EN2EVZ7N

这条规则关联到新的规则链:KUBE-SVC-BXIL3WE3EN2EVZ7N

我们查看BXIL3WE3EN2EVZ7N下一跳:

iptables-save | grep servicelayer/hello-openshift | grep -i KUBE-SVC-BXIL3WE3EN2EVZ7N

再查看其下一跳,可以看到是pod的IP:

也就是说,iptables的规则中:对server ip的访问,在经过两跳以后,转到了pod的IP上。

接下来,我们检测 Session Affinity:

oc edit service hello-openshift,将 Session Affinity:从None修改为ClientIP:

我们再次查看iptables的规则:

iptables-save | grep servicelayer/hello-openshift | grep 8080| grep -i 172.30.152.146

-A KUBE-SERVICES -d 172.30.198.53/32 -p tcp -m comment --comment "servicelayer/hello-openshift:8080-tcp cluster IP" -m tcp --dport 8080 -j KUBE-SVC-BXIL3WE3EN2EVZ7N

查看KUBE-SVC-BXIL3WE3EN2EVZ7N的下一跳:

iptables-save | grep servicelayer/hello-openshift | grep -i KUBE-SVC-BXIL3WE3EN2EVZ7N

看到修改与Session Affinity的区别了么?

规则中多了:--rcheck --seconds 10800

也就是说,从最后一个数据包开始不超过10800秒,数据包就会发送到与前一个数据包相同的目标链(pod)。否则,数据包被发送到一个随机链接(其它pod)。

四、Openshift SDN网络策略实验

在前面的实验中,OCP的OVS用的是ovs-multitenant。在本实验中,我们会使用 ovs-networkpolicy。

我们使用一个网络策略迁移脚本:migrate-network-policy.sh,让project完成从ovs-multitenant到 ovs-networkpolicy的转换。

https://raw.githubusercontent.com/openshift/origin/master/contrib/migration/migrate-network-policy.sh

执行脚本:

接下来,修改ansible配置文件,用redhat/openshift-ovs-networkpolicy替代 os_sdn_network_plugin_name,然后再次执行OCP安装脚本。

接下来,我们将部署整套应用来验证网络策略。应用架构如下:

前端服务提供UI,允许用户登录并显示所有注册用户用php编写的推文。

电子邮件服务,可以将电子邮件发送给以Python编写的注册用户,将数据保存在MySQLdb中。

Twitter服务,用于为在Tomcat上运行的Java编写的注册用户提供推文。该服务由前端HTML直接调用。

用户注册后端注册用户,将注册用户保存在MongoDB中,并用Node.Js编写。该服务由前端HTML调用并执行用户注册。一旦用户注册,它会调用电子邮件服务发送电子邮件确认。

在本测试中,将会有三个OCP的project:

msclient project: 所有前端服务。

msservices project:user-registration 后端服 和 Twitter service.

msinfra project: 所有邮件服务。

接下来部署应用:

git clone https://github.com/newgoliath/microservices-on-openshift

oc new-project msclient

oc new-project msservices

oc new-project msinfra

修改1.setVariable.sh,在里面我设置了个人的谷歌邮箱:

source 2.deployEmailSvc-PythonMySQL.sh

source 3.deployTwitter-Tomcat.sh

source 4.deployUserRegBackend-NodejsMongo.sh

source 5.deployFrontend-PHP.sh

接下来,查看部署的应用:

通过浏览器访问route,可以显示出如下内容:

接下来,我们注册几个账户:

接下来,根据注册的用户,可以登录:

接下来,针对这套微服务,我们增加网络安全策略。

首先,我们让所有对msclient项目的网络请求都被拒绝。

再次访问浏览器:

此时loadbalance到pod是8080端口。

接下来,我们单独放开8080端口:

再次访问浏览器,可以访问了:

五、Openshift对计算资源管理

OCP对计算资源的管理,可以通过limits实现。同时配置HPA,已确保pod可以实现自动弹性伸缩。

创建HPA测试的项目和应用:

oc new-project test-hpa

oc new-app openshift/hello-openshift:v1.1.1.1 -n test-hpa

创建limits:

[root@master2 installscripts]# cat limits.json

{
    "kind": "LimitRange",
    "apiVersion": "v1",
    "metadata": {
        "name": "limits",
        "creationTimestamp": null
    },
    "spec": {
        "limits": [
            {
                "type": "Pod",
                "max": {
                    "cpu": "100m",
                    "memory": "750Mi"
                },
                "min": {
                    "cpu": "10m",
                    "memory": "5Mi"
                }
            },
            {
                "type": "Container",
                "max": {
                    "cpu": "100m",
                    "memory": "750Mi"
                },
                "min": {
                    "cpu": "10m",
                    "memory": "5Mi"
                },
                "default": {
                    "cpu": "50m",
                    "memory": "100Mi"
                }
            }
        ]
    }
}

配置HPA参数:

接下来,通过一个脚本对应用加压:

[root@master1 ~]# IP=$(oc get svc hello-openshift --template "{{ .spec.portalIP }}")[root@master1 ~]# for time in {1..15000} do echo time $time curl ${IP}:8080 done

pod发生了自动扩容: