k8s-openshift-okd随笔-生活工作点滴

Openshift上部署OpenLDAP实战:为账号一统

2019-07-10  本文已影响178人  潘晓华Michael
账号一统

Openshift上部署OpenLDAP也并不仅仅只是为了部署,更重要的是要用它来为各种应用统一账号管理。比如GitLab,Gogs, Nexus, Sonarqube等等,同时结合之前的Openshift使用OpenLDAP做账号管理。理想的世界是,一套Openshift,各种应用,它们的用户认证都在一套OpenLDAP上,同时这套OpenLDAP也是非常方便地部署在Openshift上。

为账号一统的第一步,就是我们需要部署OpenLDAP,这也是该篇主题。以下是之前分享的几篇与OpenLDAP有关的文章。

CentOS上搭建双主高可用OpenLDAP Server
Openshift使用OpenLDAP作为统一用户认证
CentOS上OpenLDAP Server使用cn=config方式配置

之前分享的与Openldap相关的几篇文章中,它的部署都是在虚拟机中进行的。那么在Openshift上能否完成部署呢,如果可以的话,那么那些复杂的部署我们都可以将它封装到镜像中去,岂不是更方便?那就一起来操作吧。

应用要求点

  1. 方便自定义域及管理员用户名与密码
    通过环境变量secret进行自定义配置
  2. 对pod添加健康检查,如果发现问题,主动重启恢复
    监听389端口
  3. 数据持久化,pod重启后,该pod自动恢复数据
    持久化目录为:数据目录 /var/lib/ldap, 配置目录 /etc/openldap

以上是在Openshift运行Openldap的最基本的要求了,如果更苛刻点,需要添加Openldap的监控、Openldap的日志审计、多pod高可用方案等。

制作镜像

如果不希望自己构建,可以直接使用构建好的镜像:docker.io/xhuaustc/openldap-2441-centos7:latest
步骤如下:

  1. 基础镜像centos:centos7
  2. 安装openldap相关应用:openldap, openldap-clients, openldap-servers
  3. 部署:根据环境变量更新openldap的配置文件,并初始化基础结构,最后启动openldap
    运行:启动openldap

说明,部署与运行的区别在于该应用是否是第一次启动。如果是第一次启动的话,相关配置还未更新。在第一次配置更新后,在持久化文件夹中创建一个新文件,来标记已完成配置更新。以后的每次启动都会检查该文件,如果存在,则不作初始化操作,而直接运行openldap

对应的Dockerfile参考:https://github.com/openshift/openldap/blob/master/2.4.41/Dockerfile

FROM centos:centos7

# OpenLDAP server image for OpenShift Origin
#
# Volumes:
# * /var/lib/ldap/data - Datastore for OpenLDAP
# * /etc/openldap/     - Config directory for slapd
# Environment:
# * $OPENLDAP_ADMIN_PASSWORD         - OpenLDAP administrator password
# * $OPENLDAP_DEBUG_LEVEL (Optional) - OpenLDAP debugging level, defaults to 256

MAINTAINER Steve Kuznetsov <skuznets@redhat.com>

LABEL io.k8s.description="OpenLDAP is an open source implementation of the Lightweight Directory Access Protocol." \
      io.k8s.display-name="OpenLDAP 2.4.41" \
      io.openshift.expose-services="389:ldap,636:ldaps" \
      io.openshift.tags="directory,ldap,openldap,openldap2441" \
      io.openshift.non-scalable="true"

# Add defaults for config
COPY ./contrib/config /opt/openshift/config
COPY ./contrib/lib /opt/openshift/lib
# Add startup scripts
COPY run-*.sh /usr/local/bin/
COPY contrib/*.ldif /usr/local/etc/openldap/
COPY contrib/*.schema /usr/local/etc/openldap/
COPY contrib/DB_CONFIG /usr/local/etc/openldap/

# Install OpenLDAP Server, give it permissionst to bind to low ports
RUN yum install -y openldap openldap-servers openldap-clients && \
    yum clean all -y && \
    setcap 'cap_net_bind_service=+ep' /usr/sbin/slapd && \
    mkdir -p /var/lib/ldap && \
    chmod a+rwx -R /var/lib/ldap && \
    mkdir -p /etc/openldap && \
    chmod a+rwx -R /etc/openldap && \
    mkdir -p /var/run/openldap && \
    chmod a+rwx -R /var/run/openldap && \
    chmod -R a+rw /opt/openshift 

# Set OpenLDAP data and config directories in a data volume
VOLUME ["/var/lib/ldap", "/etc/openldap"]

# Expose default ports for ldap and ldaps
EXPOSE 389 636

CMD ["/usr/local/bin/run-openldap.sh"]

对应的部署及运行脚本参考:
https://github.com/openshift/openldap/blob/master/2.4.41/run-openldap.sh
但是有所修改,如果用root用户启动时,会先初始化openldap配置。原来的脚本如果用root用户启动时,会报错,而用非root用户启动,则自定义配置无法生效。

#!/bin/bash

# Reduce maximum number of number of open file descriptors to 1024
# otherwise slapd consumes two orders of magnitude more of RAM
# see https://github.com/docker/docker/issues/8231
ulimit -n 1024

OPENLDAP_ROOT_PASSWORD=${OPENLDAP_ROOT_PASSWORD:-admin}
OPENLDAP_ROOT_DN_PREFIX=${OPENLDAP_ROOT_DN_PREFIX:-'cn=Manager'}
OPENLDAP_ROOT_DN_SUFFIX=${OPENLDAP_ROOT_DN_SUFFIX:-'dc=example,dc=com'}
OPENLDAP_DEBUG_LEVEL=${OPENLDAP_DEBUG_LEVEL:-256}

# Only run if no config has happened fully before
if [ ! -f /etc/openldap/CONFIGURED ]; then

    user=`id | grep -Po "(?<=uid=)\d+"`
    if (( user == 0 ))
    then
        # We are root, we can use user input!
        # Bring in default databse config
        cp /usr/local/etc/openldap/DB_CONFIG /var/lib/ldap/DB_CONFIG
        
if [ -f /opt/openshift/config/slapd.d/cn\=config/olcDatabase\=\{0\}config.ldif ]
        then
            # Use provided default config, get rid of current data
            rm -rf /var/lib/ldap/*
            rm -rf /etc/openldap/*
            # Bring in associated default database files
            mv -f /opt/openshift/lib/* /var/lib/ldap
            mv -f /opt/openshift/config/* /etc/openldap
        else
            # Something has gone wrong with our image build
            echo "FAILURE: Default configuration files from /contrib/ are not present in the image at /opt/openshift."
            exit 1
        fi

        # start the daemon in another process and make config changes
        slapd -h "ldap:/// ldaps:/// ldapi:///" -d $OPENLDAP_DEBUG_LEVEL &
        for ((i=30; i>0; i--))
        do
            ping_result=`ldapsearch 2>&1 | grep "Can.t contact LDAP server"`
            if [ -z "$ping_result" ]
            then
                break
            fi
            sleep 1
        done
        if [ $i -eq 0 ]
        then
            echo "slapd did not start correctly"
            exit 1
        fi

        # Generate hash of password
        OPENLDAP_ROOT_PASSWORD_HASH=$(slappasswd -s "${OPENLDAP_ROOT_PASSWORD}")

        # Update configuration with root password, root DN, and root suffix
        sed -e "s OPENLDAP_ROOT_PASSWORD ${OPENLDAP_ROOT_PASSWORD_HASH} g" \
            -e "s OPENLDAP_ROOT_DN ${OPENLDAP_ROOT_DN_PREFIX} g" \
            -e "s OPENLDAP_SUFFIX ${OPENLDAP_ROOT_DN_SUFFIX} g" /usr/local/etc/openldap/first_config.ldif |
            ldapmodify -Y EXTERNAL -H ldapi:/// -d $OPENLDAP_DEBUG_LEVEL

        # add test schema
        ldapadd -Y EXTERNAL -H ldapi:/// -f /usr/local/etc/openldap/testPerson.ldif -d $OPENLDAP_DEBUG_LEVEL

        # add useful schemas
        ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/cosine.ldif -d $OPENLDAP_DEBUG_LEVEL
        ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/inetorgperson.ldif -d $OPENLDAP_DEBUG_LEVEL

        # load memberOf and refint modules
        ldapadd -Y EXTERNAL -H ldapi:/// -f /usr/local/etc/openldap/load_modules.ldif -d $OPENLDAP_DEBUG_LEVEL

        # configure memberOf module
        ldapadd -Y EXTERNAL -H ldapi:/// -f /usr/local/etc/openldap/configure_memberof.ldif -d $OPENLDAP_DEBUG_LEVEL

        # configure refint module
        ldapadd -Y EXTERNAL -H ldapi:/// -f /usr/local/etc/openldap/configure_refint.ldif -d $OPENLDAP_DEBUG_LEVEL

        # extract dc name from root DN suffix
        dc_name=$(echo "${OPENLDAP_ROOT_DN_SUFFIX}" | grep -Po "(?<=^dc\=)[\w\d]+")
        # create base organization object
        sed -e "s OPENLDAP_SUFFIX ${OPENLDAP_ROOT_DN_SUFFIX} g" \
            -e "s FIRST_PART ${dc_name} g" \
            usr/local/etc/openldap/base.ldif |
            ldapadd -x -D "$OPENLDAP_ROOT_DN_PREFIX,$OPENLDAP_ROOT_DN_SUFFIX" -w "$OPENLDAP_ROOT_PASSWORD"

        # stop the daemon
        pid=$(ps -A | grep slapd | awk '{print $1}')
        kill -2 $pid || echo $?

        # ensure the daemon stopped
        for ((i=30; i>0; i--))
        do
            exists=$(ps -A | grep $pid)
            if [ -z "${exists}" ]
            then
                break
            fi
            sleep 1
        done
        if [ $i -eq 0 ]
        then
            echo "slapd did not stop correctly"
            exit 1
        fi
    else
        # We are not root, we need to populate from the default bind-mount source
        if [ -f /opt/openshift/config/slapd.d/cn\=config/olcDatabase\=\{0\}config.ldif ]
        then
            # Use provided default config, get rid of current data
            rm -rf /var/lib/ldap/*
            rm -rf /etc/openldap/*
            # Bring in associated default database files
            mv -f /opt/openshift/lib/* /var/lib/ldap
            mv -f /opt/openshift/config/* /etc/openldap
        else
            # Something has gone wrong with our image build
            echo "FAILURE: Default configuration files from /contrib/ are not present in the image at /opt/openshift."
            exit 1
        fi
    fi

    # Test configuration files, log checksum errors. Errors may be tolerated and repaired by slapd so don't exit
    LOG=`slaptest 2>&1`
    CHECKSUM_ERR=$(echo "${LOG}" | grep -Po "(?<=ldif_read_file: checksum error on \").+(?=\")")
    for err in $CHECKSUM_ERR
    do
        echo "The file ${err} has a checksum error. Ensure that this file is not edited manually, or re-calculate the checksum."
    done

    rm -rf /opt/openshift/*

    touch /etc/openldap/CONFIGURED
fi

# Start the slapd service
exec slapd -h "ldap:/// ldaps:///" -d $OPENLDAP_DEBUG_LEVEL

说明,本来我是准备按照之前部署经验自己写一个镜像构建,但是写到一半的时候,发现整个逻辑与openshift官方提供的差不多,所以就直接用官方的了。
从脚本中可以看到管理员(一般为cn=Manager)密码数据库管理员(一般为cn=config)密码是一样的,都是通过环境变量OPENLDAP_ROOT_PASSWORD配置。

变量名 说明 默认值
OPENLDAP_ROOT_PASSWORD OpenLDAP olcRootPW 密码 admin
OPENLDAP_ROOT_DN_SUFFIX OpenLDAP olcSuffix 域前缀 dc=example,dc=com
OPENLDAP_ROOT_DN_PREFIX OpenLDAP olcRootDN 前缀 cn=Manager
OPENLDAP_DEBUG_LEVEL OpenLDAP服务日志级别 256

使用openshift/openldap进行构建镜像操作

$ git clone https://github.com/openshift/openldap.git
$ cd openldap
$ export SKIP_SQUASH=1 && make build    #构建出的镜像名为:openshift/openldap-2441-centos7:latest

部署Openldap

两种方法实现部署:
第一种. 使用openshift的client工具部署

$ #创建项目
$ oc new-project openldap --display-name=OpenLDAP 
$ #创建单独的serviceaccount为方便以root用户启动pod
$ oc create serviceaccount openldap  
$  #为openldap serviceaccount赋予以root启动pod的权限
$ oc adm policy add-scc-to-user anyuid -z openldap
$ #创建secret,设置openldap的域与密码
$ oc create secret generic openldap --from-literal=OPENLDAP_ROOT_PASSWORD=admin --from-literal=OPENLDAP_ROOT_DN_SUFFIX=dc=fcloudy,dc=com 
$ # 部署应用(默认会是以default serviceaccount运行)
$ oc new-app  --docker-image=xhuaustc/openldap-2441-centos7 --name=openldap 
$ #为应用设置环境变量,即为openldap的域与密码
$ oc env --from=secret/openldap dc/openldap 
$ #为应用设置以openldap serviceaccount启动
$ cat << EOF | oc apply -f -
apiVersion: apps.openshift.io/v1
kind: DeploymentConfig
metadata:
  name: openldap
spec:
  template:
    spec:
      serviceAccount: openldap
EOF

当然以上配置没有添加健康检查,以及持久化是使用的emptyDir。这个可以后序自己补充。

第二种:使用yaml配置文件部署,主要是DeploymentConfig的配置。添加了健康检查

$ cat << EOF | oc create -f -
apiVersion: apps.openshift.io/v1
kind: DeploymentConfig
metadata:
  labels:
    app: openldap
  name: openldap
spec:
  replicas: 1
  selector:
    app: openldap
    deploymentconfig: openldap
  template:
    metadata:
      labels:
        app: openldap
        deploymentconfig: openldap
    spec:
      containers:
        - env:
            - name: OPENLDAP_ROOT_DN_SUFFIX
              valueFrom:
                secretKeyRef:
                  key: OPENLDAP_ROOT_DN_SUFFIX
                  name: openldap
            - name: OPENLDAP_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  key: OPENLDAP_ROOT_PASSWORD
                  name: openldap
          image: 'xhuaustc/openldap-2441-centos7:latest'
          imagePullPolicy: Always
          livenessProbe:
            failureThreshold: 3
            initialDelaySeconds: 3
            periodSeconds: 10
            successThreshold: 1
            tcpSocket:
              port: 389
            timeoutSeconds: 1
          name: openldap
          ports:
            - containerPort: 389
              protocol: TCP
            - containerPort: 636
              protocol: TCP
          readinessProbe:
            failureThreshold: 3
            initialDelaySeconds: 3
            periodSeconds: 10
            successThreshold: 1
            tcpSocket:
              port: 389
            timeoutSeconds: 1
          name: openldap
          ports:
            - containerPort: 389
              protocol: TCP
            - containerPort: 636
              protocol: TCP
          volumeMounts:
            - mountPath: /etc/openldap
              name: openldap-volume-1
            - mountPath: /var/lib/ldap
              name: openldap-volume-2
      volumes:
        - emptyDir: {}
          name: openldap-volume-1
        - emptyDir: {}
          name: openldap-volume-2
  triggers:
    - type: ConfigChange

测试验证

按照以上部署的配置,管理员账号为:cn=Manager,dc=fcloudy,dc=com,密码为:admin
使用LDAPBrowser连接

连接设置 连接成功

最后一步,做成模板

将资源导出为模板文件

$ oc export dc,svc,secret  --as-template=openldap > openldap-template.yaml

在此基础上手动编辑,最后得到可用的模板文件

apiVersion: template.openshift.io/v1
kind: Template
message: |-
  OpenLDAP服务将会根据指定的参数创建
metadata:
  annotations:
    description: |-
      OpenLDAP服务将会根据指定的参数创建
  name: openldap
objects:
- apiVersion: apps.openshift.io/v1
  kind: DeploymentConfig
  metadata:
    labels:
      app: openldap
    name: openldap
  spec:
    replicas: 1
    selector:
      app: openldap
      deploymentconfig: openldap
    strategy:
      type: Rolling
    template:
      metadata:
        labels:
          app: openldap
          deploymentconfig: openldap
      spec:
        containers:
        - env:
          - name: OPENLDAP_ROOT_DN_SUFFIX
            valueFrom:
              secretKeyRef:
                key: OPENLDAP_ROOT_DN_SUFFIX
                name: openldap
          - name: OPENLDAP_ROOT_PASSWORD
            valueFrom:
              secretKeyRef:
                key: OPENLDAP_ROOT_PASSWORD
                name: openldap
          - name: OPENLDAP_ROOT_DN_PREFIX
            valueFrom:
              secretKeyRef:
                key: OPENLDAP_ROOT_DN_PREFIX
                name: openldap
          - name: OPENLDAP_DEBUG_LEVEL
            valueFrom:
              secretKeyRef:
                key: OPENLDAP_DEBUG_LEVEL
                name: openldap
          image: xhuaustc/openldap-2441-centos7:latest
          imagePullPolicy: IfNotPresent
          name: openldap
          ports:
          - containerPort: 389
            protocol: TCP
          - containerPort: 636
            protocol: TCP
          volumeMounts:
          - mountPath: /etc/openldap
            name: openldap-volume-1
          - mountPath: /var/lib/ldap
            name: openldap-volume-2
        restartPolicy: Always
        serviceAccount: openldap
        serviceAccountName: openldap
        volumes:
        - emptyDir: {}
          name: openldap-volume-1
        - emptyDir: {}
          name: openldap-volume-2
    triggers:
    - type: ConfigChange
- apiVersion: v1
  kind: Service
  metadata:
    labels:
      app: openldap
    name: openldap
  spec:
    ports:
    - name: 389-tcp
      port: 389
      protocol: TCP
      targetPort: 389
    - name: 636-tcp
      port: 636
      protocol: TCP
      targetPort: 636
    selector:
      app: openldap
      deploymentconfig: openldap
    sessionAffinity: None
    type: ClusterIP
- apiVersion: v1
  stringData:
    OPENLDAP_ROOT_DN_SUFFIX: ${OPENLDAP_ROOT_DN_SUFFIX}
    OPENLDAP_ROOT_DN_PREFIX: ${OPENLDAP_ROOT_DN_PREFIX}
    OPENLDAP_ROOT_PASSWORD: ${OPENLDAP_ROOT_PASSWORD}
    OPENLDAP_DEBUG_LEVEL: ${OPENLDAP_DEBUG_LEVEL}
  kind: Secret
  metadata:
    name: openldap
  type: Opaque
parameters:
- description: Openldap Root DN Suffix
  displayName: Openldap Root DN Suffix
  name: OPENLDAP_ROOT_DN_SUFFIX
  value: dc=example,dc=com
- description: Openldap Root DN Manager Prefix
  displayName: Openldap Root DN Manager Prefix
  name: OPENLDAP_ROOT_DN_PREFIX
  value: cn=Manager
- description: Openldap Root Password
  displayName: Openldap Root Password
  name: OPENLDAP_ROOT_PASSWORD
  from: '[a-zA-Z0-9]{16}'
  generate: expression
- description: Openldap Debug Level
  displayName: Openldap Debug Level
  name: OPENLDAP_DEBUG_LEVEL
  value: "256"

在Openshift上将模板导入,完成后,创建Openldap就非常简单了,看截图。

Openshift模板创建OpenLDAP

ps:OpenLDAP的整个构建及部署过程可以作为Openshift的一种类型案例。当然该案例中没有使用PV、PVC做持久化。相信对Openshift有所了解的,在这个基础上做持久化应该不在话下。

千里之行,始于足下。完成OpenLDAP的部署,这只是一个开始,账号一统还有相当多的工作要去做。

欢迎关注
上一篇 下一篇

猜你喜欢

热点阅读