美文网首页k8s-openshift-okd随笔-生活工作点滴
Openshift上部署OpenLDAP实战:为账号一统

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

作者: 潘晓华Michael | 来源:发表于2019-07-10 17:59 被阅读178次
    账号一统

    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的部署,这只是一个开始,账号一统还有相当多的工作要去做。

    欢迎关注

    相关文章

      网友评论

        本文标题:Openshift上部署OpenLDAP实战:为账号一统

        本文链接:https://www.haomeiwen.com/subject/nmoxkctx.html