You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@doris.apache.org by yi...@apache.org on 2024/04/12 15:12:22 UTC

(doris) 23/24: [k8s](improve)add docker resource script for k8s (#33329)

This is an automated email from the ASF dual-hosted git repository.

yiguolei pushed a commit to branch branch-2.1
in repository https://gitbox.apache.org/repos/asf/doris.git

commit 19ce67af5709222898d690b3a16dba258869441c
Author: Liqf <10...@users.noreply.github.com>
AuthorDate: Fri Apr 12 17:59:39 2024 +0800

    [k8s](improve)add docker resource script for k8s (#33329)
---
 docker/runtime/be/Dockerfile                       |   5 +-
 docker/runtime/be/resource/be_entrypoint.sh        | 244 +++++++++++++
 docker/runtime/be/resource/be_prestop.sh           |  21 ++
 docker/runtime/be/resource/entry_point.sh          |   0
 docker/runtime/be/resource/init_be.sh              |   2 +-
 docker/runtime/broker/Dockerfile                   |  54 ++-
 .../runtime/broker/resource/broker_entrypoint.sh   | 222 ++++++++++++
 docker/runtime/broker/resource/broker_is_alive.sh  |  39 ++
 docker/runtime/broker/resource/broker_prestop.sh   |  21 ++
 docker/runtime/broker/resource/init_broker.sh      |   2 +-
 docker/runtime/fe/Dockerfile                       |   6 +-
 docker/runtime/fe/resource/fe_check_master.sh      |  42 +++
 docker/runtime/fe/resource/fe_entrypoint.sh        | 395 +++++++++++++++++++++
 docker/runtime/fe/resource/fe_prestop.sh           |  21 ++
 docker/runtime/fe/resource/init_fe.sh              |   6 +-
 15 files changed, 1055 insertions(+), 25 deletions(-)

diff --git a/docker/runtime/be/Dockerfile b/docker/runtime/be/Dockerfile
index e890f053237..1e1b4505764 100644
--- a/docker/runtime/be/Dockerfile
+++ b/docker/runtime/be/Dockerfile
@@ -1,4 +1,3 @@
-#!/bin/bash
 # Licensed to the Apache Software Foundation (ASF) under one
 # or more contributor license agreements.  See the NOTICE file
 # distributed with this work for additional information
@@ -51,10 +50,14 @@ ADD resource/apache-doris-${DORIS_VERSION}-bin-${TARGETARCH:-amd64}/be /opt/apac
 
 COPY resource/be_*.sh /opt/apache-doris/
 
+COPY --from=selectdb/doris-debug-ubuntu:latest /doris-debug /opt/apache-doris/
+
 COPY resource/entry_point.sh /usr/local/bin/
 
 COPY resource/init_be.sh /usr/local/bin/
 
+#RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
+
 WORKDIR /opt/apache-doris
 
 ENTRYPOINT ["bash","entry_point.sh"]
diff --git a/docker/runtime/be/resource/be_entrypoint.sh b/docker/runtime/be/resource/be_entrypoint.sh
new file mode 100755
index 00000000000..4c1ca21ba94
--- /dev/null
+++ b/docker/runtime/be/resource/be_entrypoint.sh
@@ -0,0 +1,244 @@
+#!/bin/bash
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+
+# the fe query port for mysql.
+FE_QUERY_PORT=${FE_QUERY_PORT:-9030}
+# timeout for probe fe master.
+PROBE_TIMEOUT=60
+# interval time to probe fe.
+PROBE_INTERVAL=2
+# rpc port for fe communicate with be.
+HEARTBEAT_PORT=9050
+# fqdn or ip
+MY_SELF=
+MY_IP=`hostname -i`
+MY_HOSTNAME=`hostname -f`
+DORIS_ROOT=${DORIS_ROOT:-"/opt/apache-doris"}
+# if config secret for basic auth about operate node of doris, the path must be `/etc/basic_auth`. This is set by operator and the key of password must be `password`.
+AUTH_PATH="/etc/basic_auth"
+DORIS_HOME=${DORIS_ROOT}/be
+BE_CONFIG=$DORIS_HOME/conf/be.conf
+# represents self in fe meta or not.
+REGISTERED=false
+
+DB_ADMIN_USER=${USER:-"root"}
+
+DB_ADMIN_PASSWD=$PASSWD
+
+log_stderr()
+{
+    echo "[`date`] $@" >&2
+}
+
+update_conf_from_configmap()
+{
+    if [[ "x$CONFIGMAP_MOUNT_PATH" == "x" ]] ; then
+        log_stderr '[info] Empty $CONFIGMAP_MOUNT_PATH env var, skip it!'
+        return 0
+    fi
+    if ! test -d $CONFIGMAP_MOUNT_PATH ; then
+        log_stderr "[info] $CONFIGMAP_MOUNT_PATH not exist or not a directory, ignore ..."
+        return 0
+    fi
+    local tgtconfdir=$DORIS_HOME/conf
+    for conffile in `ls $CONFIGMAP_MOUNT_PATH`
+    do
+        log_stderr "[info] Process conf file $conffile ..."
+        local tgt=$tgtconfdir/$conffile
+        if test -e $tgt ; then
+            # make a backup
+            mv -f $tgt ${tgt}.bak
+        fi
+        ln -sfT $CONFIGMAP_MOUNT_PATH/$conffile $tgt
+    done
+}
+
+# resolve password for root
+resolve_password_from_secret()
+{
+    if [[ -f "$AUTH_PATH/password" ]]; then
+        DB_ADMIN_PASSWD=`cat $AUTH_PATH/password`
+    fi
+    if [[ -f "$AUTH_PATH/username" ]]; then
+        DB_ADMIN_USER=`cat $AUTH_PATH/username`
+    fi
+}
+
+# get all backends info to check self exist or not.
+show_backends(){
+    local svc=$1
+    backends=`timeout 15 mysql --connect-timeout 2 -h $svc -P $FE_QUERY_PORT -uroot --skip-column-names --batch -e 'SHOW BACKENDS;' 2>&1`
+    log_stderr "[info] use root no password show backends result $backends ."
+    if echo $backends | grep -w "1045" | grep -q -w "28000" &>/dev/null; then
+        log_stderr "[info] use username and password that configured to show backends."
+        backends=`timeout 15 mysql --connect-timeout 2 -h $svc -P $FE_QUERY_PORT -u$DB_ADMIN_USER -p$DB_ADMIN_PASSWD --skip-column-names --batch -e 'SHOW BACKENDS;'`
+    fi
+
+    echo "$backends"
+
+    #if [[ "x$DB_ADMIN_PASSWD" != "x" ]]; then
+    #   timeout 15 mysql --connect-timeout 2 -h $svc -P $FE_QUERY_PORT -u$DB_ADMIN_USER -p$DB_ADMIN_PASSWD --skip-column-names --batch -e 'SHOW BACKENDS;'
+    #else
+    #   timeout 15 mysql --connect-timeout 2 -h $svc -P $FE_QUERY_PORT -u$DB_ADMIN_USER --skip-column-names --batch -e 'SHOW BACKENDS;'
+    #fi
+}
+
+# get all registered fe in cluster, for check the fe have `MASTER`.
+function show_frontends()
+{
+    local addr=$1
+    frontends=`timeout 15 mysql --connect-timeout 2 -h $addr -P $FE_QUERY_PORT -uroot --batch -e 'show frontends;' 2>&1`
+    log_stderr "[info] use root no password show frontends result $frontends ."
+    if echo $frontends | grep -w "1045" | grep -q -w "28000" &>/dev/null; then
+        log_stderr "[info] use username and passwore that configured to show frontends."
+        frontends=`timeout 15 mysql --connect-timeout 2 -h $addr -P $FE_QUERY_PORT -u$DB_ADMIN_USER -p$DB_ADMIN_PASSWD --batch -e 'show frontends;'`
+    fi
+
+    echo "$frontends"
+    #if [[ "x$DB_ADMIN_PASSWD" != "x" ]]; then
+    #    timeout 15 mysql --connect-timeout 2 -h $addr -P $FE_QUERY_PORT -u$DB_ADMIN_USER -p$DB_ADMIN_PASSWD --batch -e 'show frontends;'
+    #else
+    #    timeout 15 mysql --connect-timeout 2 -h $addr -P $FE_QUERY_PORT -u$DB_ADMIN_USER --batch -e 'show frontends;'
+    #fi
+}
+
+#parse the `$BE_CONFIG` file, passing the key need resolve as parameter.
+parse_confval_from_conf()
+{
+    # a naive script to grep given confkey from fe conf file
+    # assume conf format: ^\s*<key>\s*=\s*<value>\s*$
+    local confkey=$1
+    local confvalue=`grep "\<$confkey\>" $BE_CONFIG | grep -v '^\s*#' | sed 's|^\s*'$confkey'\s*=\s*\(.*\)\s*$|\1|g'`
+    echo "$confvalue"
+}
+
+collect_env_info()
+{
+    # heartbeat_port from conf file
+    local heartbeat_port=`parse_confval_from_conf "heartbeat_service_port"`
+    if [[ "x$heartbeat_port" != "x" ]] ; then
+        HEARTBEAT_PORT=$heartbeat_port
+    fi
+
+    if [[ "x$HOST_TYPE" == "xIP" ]] ; then
+        MY_SELF=$MY_IP
+    else
+        MY_SELF=$MY_HOSTNAME
+    fi
+}
+
+add_self()
+{
+    local svc=$1
+    start=`date +%s`
+    local timeout=$PROBE_TIMEOUT
+
+    while true
+    do
+        memlist=`show_backends $svc`
+        if echo "$memlist" | grep -q -w "$MY_SELF" &>/dev/null ; then
+            log_stderr "[info] Check myself ($MY_SELF:$HEARTBEAT_PORT) exist in FE, start be directly ..."
+            break;
+        fi
+
+        # check fe cluster have master, if fe have not master wait.
+        fe_memlist=`show_frontends $svc`
+        local pos=`echo "$fe_memlist" | grep '\<IsMaster\>' | awk -F '\t' '{for(i=1;i<NF;i++) {if ($i == "IsMaster") print i}}'`
+        local leader=`echo "$fe_memlist" | grep '\<FOLLOWER\>' | awk -v p="$pos" -F '\t' '{if ($p=="true") print $2}'`
+        log_stderr "'IsMaster' sequence in columns is $pos master=$leader ."
+
+        if [[ "x$leader" == "x" ]]; then
+            log_stderr "[info] resolve the eighth column for finding master !"
+            leader=`echo "$fe_memlist" | grep '\<FOLLOWER\>' | awk -F '\t' '{if ($8=="true") print $2}'`
+        fi
+        if [[ "x$leader" == "x" ]]; then
+            # compatible 2.1.0
+            log_stderr "[info] resoluve the ninth column for finding master!"
+            leader=`echo "$fe_memlist" | grep '\<FOLLOWER\>' | awk -F '\t' '{if ($9=="true") print $2}'`
+        fi
+
+        if [[ "x$leader" != "x" ]]; then
+            log_stderr "[info] myself ($MY_SELF:$HEARTBEAT_PORT)  not exist in FE and fe have leader register myself into fe."
+            add_result=`timeout 15 mysql --connect-timeout 2 -h $svc -P $FE_QUERY_PORT -uroot --skip-column-names --batch -e "ALTER SYSTEM ADD BACKEND \"$MY_SELF:$HEARTBEAT_PORT\";" 2>&1`
+            if echo $add_result | grep -w "1045" | grep -q -w "28000" &>/dev/null ; then
+                timeout 15 mysql --connect-timeout 2 -h $svc -P $FE_QUERY_PORT -u$DB_ADMIN_USER -p$DB_ADMIN_PASSWD --skip-column-names --batch -e "ALTER SYSTEM ADD BACKEND \"$MY_SELF:$HEARTBEAT_PORT\";"
+            fi
+
+            #if [[ "x$DB_ADMIN_PASSWD" != "x" ]]; then
+            #    timeout 15 mysql --connect-timeout 2 -h $svc -P $FE_QUERY_PORT -u$DB_ADMIN_USER -p$DB_ADMIN_PASSWD --skip-column-names --batch -e "ALTER SYSTEM ADD BACKEND \"$MY_SELF:$HEARTBEAT_PORT\";"
+            #else
+            #    timeout 15 mysql --connect-timeout 2 -h $svc -P $FE_QUERY_PORT -u$DB_ADMIN_USER --skip-column-names --batch -e "ALTER SYSTEM ADD BACKEND \"$MY_SELF:$HEARTBEAT_PORT\";"
+            #fi
+
+            let "expire=start+timeout"
+            now=`date +%s`
+            if [[ $expire -le $now ]] ; then
+                log_stderr "[error]  exit probe master for probing timeout."
+                return 0
+            fi
+        else
+            log_stderr "[info] not have leader wait fe cluster elect a master, sleep 2s..."
+            sleep $PROBE_INTERVAL
+        fi
+    done
+}
+
+# check be exist or not, if exist return 0, or register self in fe cluster. when all fe address failed exit script.
+# `xxx1:port,xxx2:port` as parameter to function.
+function check_and_register()
+{
+    addrs=$1
+    local addrArr=(${addrs//,/ })
+    for addr in ${addrArr[@]}
+    do
+        add_self $addr
+
+        if [[ $REGISTERED ]]; then
+            break;
+        fi
+    done
+
+    if [[ $REGISTERED ]]; then
+        return 0
+    else
+        log_stderr  "not find master in fe cluster, please use mysql connect to fe for verfing the master exist and verify domain connectivity with two pods in different node. "
+        exit 1
+    fi
+}
+
+fe_addrs=$1
+if [[ "x$fe_addrs" == "x" ]]; then
+    echo "need fe address as paramter!"
+    echo "  Example $0 <fe_addr>"
+    exit 1
+fi
+
+update_conf_from_configmap
+# resolve password for root to manage nodes in doris.
+resolve_password_from_secret
+collect_env_info
+#add_self $fe_addr || exit $?
+check_and_register $fe_addrs
+./doris-debug --component be
+log_stderr "run start_be.sh"
+# the server will start in the current terminal session, and the log output and console interaction will be printed to that terminal
+# befor doris 2.0.2 ,doris start with : start_xx.sh
+# sine doris 2.0.2 ,doris start with : start_xx.sh --console  doc: https://doris.apache.org/docs/dev/install/standard-deployment/#version--202
+$DORIS_HOME/bin/start_be.sh --console
+
diff --git a/docker/runtime/be/resource/be_prestop.sh b/docker/runtime/be/resource/be_prestop.sh
new file mode 100755
index 00000000000..af9ab1001c6
--- /dev/null
+++ b/docker/runtime/be/resource/be_prestop.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+DORIS_ROOT=${DORIS_ROOT:-"/opt/apache-doris"}
+DORIS_HOME=${DORIS_ROOT}/be
+$DORIS_HOME/bin/stop_be.sh
diff --git a/docker/runtime/be/resource/entry_point.sh b/docker/runtime/be/resource/entry_point.sh
old mode 100644
new mode 100755
diff --git a/docker/runtime/be/resource/init_be.sh b/docker/runtime/be/resource/init_be.sh
index 5c8a4dd0563..42afd1f6754 100644
--- a/docker/runtime/be/resource/init_be.sh
+++ b/docker/runtime/be/resource/init_be.sh
@@ -161,7 +161,7 @@ _main() {
     fi
     check_be_status
     doris_note "Ready to start BE!"
-    start_be.sh --console &
+    ${DORIS_HOME}/be/bin/start_be.sh --console &
     child_pid=$!
     wait $child_pid
     exec "$@"
diff --git a/docker/runtime/broker/Dockerfile b/docker/runtime/broker/Dockerfile
index bf1e6650f7e..827b635d24f 100644
--- a/docker/runtime/broker/Dockerfile
+++ b/docker/runtime/broker/Dockerfile
@@ -1,4 +1,3 @@
-#!/bin/bash
 # Licensed to the Apache Software Foundation (ASF) under one
 # or more contributor license agreements.  See the NOTICE file
 # distributed with this work for additional information
@@ -16,26 +15,45 @@
 # specific language governing permissions and limitations
 # under the License.
 
-# choose a base image
-FROM openjdk:8u342-jdk
+# how to use Dockerfile.
+# this is dockerfile for build doris broker image on amd64.
+# when build youself image.
+# 1. pull binary from official website and decompress into resource directory that the level equals with Dockerfile_broker_ubuntu.
+# 2. untar xxxx.tar.gz in resource directory, update the dockerfile field `apache-doris-xxx`, replace with real version.
+# 3. run commad docker build -t xxx.doris.broker:xx -f Dockerfile_broker_ubuntu.
+
+# we have support buildx for amd64 and arm64 architecture image build.
+# get the binary from doris github and utar into resource, update the directory as apache-`version(example:2.0.1)`-bin-`architecture(amd64/arm64)` mode.
+#
+
+FROM ubuntu:22.04
+
+ARG TARGETARCH
+
+ARG DORIS_VERSION="x.x.x"
+
+RUN apt-get update -y &&  DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
+    patchelf gdb binutils binutils-common mysql-client \
+    curl wget less vim htop iproute2 numactl jq iotop sysstat \
+    tcpdump iputils-ping dnsutils strace lsof blktrace tzdata \
+    bpfcc-tools linux-headers-realtime linux-tools-realtime silversearcher-ag \
+    net-tools openjdk-8-jdk && \
+    rm -rf /var/lib/apt/lists/*
 
 # set environment variables
-ENV JAVA_HOME="/usr/local/openjdk-8/" \
-    PATH="/opt/apache-doris/broker/bin:$PATH"
+ENV JAVA_HOME=/usr/lib/jvm/java-8-openjdk-${TARGETARCH:-amd64}
+
+# apache-doris/broker from doris release xxxx.tar.gz
+ADD resource/apache-doris-${DORIS_VERSION}-bin-${TARGETARCH:-amd64}/extensions/apache_hdfs_broker /opt/apache-doris/apache_hdfs_broker
+
+COPY resource/broker_*.sh /opt/apache-doris/
+
+RUN chmod +x /opt/apache-doris/broker_*.sh
 
-# Download the software to the mirror, where the broker directory is synchronously compressed to the binary package of FE,
-# which needs to be decompressed and repackaged by itself, and can be replaced as needed
-ADD ./resource/apache_hdfs_broker.tar.gz /opt/
+ADD ./resource/init_broker.sh /usr/local/bin/
 
-# deploy software
-RUN apt-get update && \
-    apt-get install -y default-mysql-client && \
-    apt-get clean && \
-    mkdir /opt/apache-doris && \
-    cd /opt && \
-    mv apache_hdfs_broker /opt/apache-doris/broker
+RUN chmod 755 /usr/local/bin/init_broker.sh
 
-ADD ./resource/init_broker.sh /opt/apache-doris/broker/bin
-RUN chmod 755 /opt/apache-doris/broker/bin/init_broker.sh
+WORKDIR /opt/apache-doris
 
-ENTRYPOINT ["/opt/apache-doris/broker/bin/init_broker.sh"]
+ENTRYPOINT ["bash","init_broker.sh"]
diff --git a/docker/runtime/broker/resource/broker_entrypoint.sh b/docker/runtime/broker/resource/broker_entrypoint.sh
new file mode 100755
index 00000000000..ad06d6c958c
--- /dev/null
+++ b/docker/runtime/broker/resource/broker_entrypoint.sh
@@ -0,0 +1,222 @@
+#!/bin/bash
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# the fe query port for mysql.
+FE_QUERY_PORT=${FE_QUERY_PORT:-9030}
+# timeout for probe fe master.
+PROBE_TIMEOUT=60
+# interval time to probe fe.
+PROBE_INTERVAL=2
+# ipc port for fe/be communicate with broker.
+IPC_PORT=8000
+# fqdn or ip
+MY_SELF=
+MY_IP=`hostname -i`
+MY_HOSTNAME=`hostname -f`
+DORIS_ROOT=${DORIS_ROOT:-"/opt/apache-doris"}
+AUTH_PATH="/etc/basic_auth"
+DORIS_HOME=${DORIS_ROOT}/apache_hdfs_broker
+BK_CONFIG=$DORIS_HOME/conf/apache_hdfs_broker.conf
+BK_NAME=broker001
+# represents self in fe meta or not.
+REGISTERED=false
+
+DB_ADMIN_USER=${USER:-"root"}
+
+DB_ADMIN_PASSWD=$PASSWD
+
+log_stderr()
+{
+    echo "[`date`] $@" >&2
+}
+
+parse_confval_from_bk_conf()
+{
+    # a naive script to grep given confkey from broker conf file
+    # assume conf format: ^\s*<key>\s*=\s*<value>\s*$
+    local confkey=$1
+    local confvalue=`grep "\<$confkey\>" $BK_CONFIG | grep -v '^\s*#' | sed 's|^\s*'$confkey'\s*=\s*\(.*\)\s*$|\1|g'`
+    echo "$confvalue"
+}
+
+update_conf_from_configmap()
+{
+    if [[ "x$CONFIGMAP_MOUNT_PATH" == "x" ]] ; then
+        log_stderr '[info] Empty $CONFIGMAP_MOUNT_PATH env var, skip it!'
+        return 0
+    fi
+    if ! test -d $CONFIGMAP_MOUNT_PATH ; then
+        log_stderr "[info] $CONFIGMAP_MOUNT_PATH not exist or not a directory, ignore ..."
+        return 0
+    fi
+    local tgtconfdir=$DORIS_HOME/conf
+    for conffile in `ls $CONFIGMAP_MOUNT_PATH`
+    do
+        log_stderr "[info] Process conf file $conffile ..."
+        local tgt=$tgtconfdir/$conffile
+        if test -e $tgt ; then
+            # make a backup
+            mv -f $tgt ${tgt}.bak
+        fi
+        ln -sfT $CONFIGMAP_MOUNT_PATH/$conffile $tgt
+    done
+}
+
+
+
+# get all brokers info to check self exist or not.
+show_brokers(){
+    local svc=$1
+    brokers=`timeout 15 mysql --connect-timeout 2 -h $svc -P $FE_QUERY_PORT -uroot --skip-column-names --batch -e 'SHOW BROKER;' 2>&1`
+    if echo $brokers | grep -w "1045" | grep -q -w "28000" &>/dev/null ; then
+        brokers=`timeout 15 mysql --connect-timeout 2 -h $svc -P $FE_QUERY_PORT -u$DB_ADMIN_USER -p$DB_ADMIN_PASSWD --skip-column-names --batch -e 'SHOW BROKER;' 2>&1`
+    fi
+    echo "$brokers"
+
+    #if [[ "x$DB_ADMIN_PASSWD" != "x" ]]; then
+    #    timeout 15 mysql --connect-timeout 2 -h $svc -P $FE_QUERY_PORT -u$DB_ADMIN_USER -p$DB_ADMIN_PASSWD --skip-column-names --batch -e 'SHOW BROKER;'
+    #else
+    #    timeout 15 mysql --connect-timeout 2 -h $svc -P $FE_QUERY_PORT -u$DB_ADMIN_USER --skip-column-names --batch -e 'SHOW BROKER;'
+    #fi
+}
+
+
+ ## ALTER SYSTEM ADD BROKER broker_name "broker_host1:broker_ipc_port1","broker_host2:broker_ipc_port2",...;
+
+# get all registered fe in cluster, for check the fe have `MASTER`.
+function show_frontends()
+{
+    local addr=$1
+    frontends=`timeout 15 mysql --connect-timeout 2 -h $addr -P $FE_QUERY_PORT -uroot --batch -e 'show frontends;' 2>&1`
+    if echo $frontends | grep -w "1045" | grep -q -w "28000" &>/dev/nulll ; then
+	frontends=`timeout 15 mysql --connect-timeout 2 -h $addr -P $FE_QUERY_PORT -u$DB_ADMIN_USER -p$DB_ADMIN_PASSWD --batch -e 'show frontends;'`
+    fi
+    echo "$frontends"
+
+    #if [[ "x$DB_ADMIN_PASSWD" != "x" ]]; then
+    #    timeout 15 mysql --connect-timeout 2 -h $addr -P $FE_QUERY_PORT -u$DB_ADMIN_USER -p$DB_ADMIN_PASSWD --skip-column-names --batch -e 'show frontends;'
+    #else
+    #    timeout 15 mysql --connect-timeout 2 -h $addr -P $FE_QUERY_PORT -u$DB_ADMIN_USER --skip-column-names --batch -e 'show frontends;'
+    #fi
+}
+
+collect_env_info()
+{
+    # IPC_PORT from conf file
+    local ipc_port=`parse_confval_from_bk_conf "broker_ipc_port"`
+    if [[ "x$ipc_port" != "x" ]] ; then
+        IPC_PORT=$ipc_port
+    fi
+
+    if [[ "x$HOST_TYPE" == "xIP" ]] ; then
+        MY_SELF=$MY_IP
+    else
+        MY_SELF=$MY_HOSTNAME
+    fi
+}
+
+add_self()
+{
+    local svc=$1
+    start=`date +%s`
+    local timeout=$PROBE_TIMEOUT
+
+    while true
+    do
+        memlist=`show_brokers $svc`
+        if echo "$memlist" | grep -q -w "$MY_SELF" &>/dev/null ; then
+            log_stderr "[info] Check myself ($MY_SELF:$IPC_PORT)  exist in FE start broker directly ..."
+            break;
+        fi
+
+        # check fe cluster have master, if fe have not master wait.
+        fe_memlist=`show_frontends $svc`
+
+        #local leader=`echo "$fe_memlist" | grep '\<FOLLOWER\>' | awk -F '\t' '{if ($8=="true") print $2}'`
+        local pos=`echo "$fe_memlist" | grep '\<IsMaster\>' | awk -F '\t' '{for(i=1;i<NF;i++) {if ($i == "IsMaster") print i}}'`
+        local leader=`echo "$fe_memlist" | grep '\<FOLLOWER\>' | awk -v p="$pos" -F '\t' '{if ($p=="true") print $2}'`
+        if [[ "x$leader" != "x" ]]; then
+            log_stderr "[info] myself ($MY_SELF:$IPC_PORT)  not exist in FE and fe have leader register myself into fe..."
+
+            add_result=`timeout 15 mysql --connect-timeout 2 -h $svc -P $FE_QUERY_PORT -uroot --skip-column-names --batch -e "ALTER SYSTEM ADD BROKER $BK_NAME \"$MY_SELF:$IPC_PORT\";" 2>&1`
+            if echo $add_result | grep -w "1045" | grep -q -w "28000" &>/dev/null ; then
+                timeout 15 mysql --connect-timeout 2 -h $svc -P $FE_QUERY_PORT -u$DB_ADMIN_USER -p$DB_ADMIN_PASSWD --skip-column-names --batch -e "ALTER SYSTEM ADD BROKER $BK_NAME \"$MY_SELF:$IPC_PORT\";"
+            fi
+
+            #if [[ "x$DB_ADMIN_PASSWD" != "x" ]]; then
+            #    timeout 15 mysql --connect-timeout 2 -h $svc -P $FE_QUERY_PORT -u$DB_ADMIN_USER -p$DB_ADMIN_PASSWD --skip-column-names --batch -e "ALTER SYSTEM ADD BROKER $BK_NAME \"$MY_SELF:$IPC_PORT\";"
+            #else
+            #    timeout 15 mysql --connect-timeout 2 -h $svc -P $FE_QUERY_PORT -u$DB_ADMIN_USER --skip-column-names --batch -e "ALTER SYSTEM ADD BROKER $BK_NAME \"$MY_SELF:$IPC_PORT\";"
+            #fi
+
+            let "expire=start+timeout"
+            now=`date +%s`
+            if [[ $expire -le $now ]] ; then
+                log_stderr "[error]  exit probe master for probing timeout."
+                return 0
+            fi
+        else
+            log_stderr "[info] not have leader wait fe cluster select a master, sleep 2s..."
+            sleep $PROBE_INTERVAL
+        fi
+    done
+}
+
+# check be exist or not, if exist return 0, or register self in fe cluster. when all fe address failed exit script.
+# `xxx1:port,xxx2:port` as parameter to function.
+function check_and_register()
+{
+    addrs=$1
+    local addrArr=(${addrs//,/ })
+    for addr in ${addrArr[@]}
+    do
+        add_self $addr
+    done
+
+    if [[ $REGISTERED ]]; then
+        return 0
+    else
+        exit 1
+    fi
+}
+
+resolve_password_from_secret()
+{
+    if [[ -f "$AUTH_PATH/password" ]]; then
+        DB_ADMIN_PASSWD=`cat $AUTH_PATH/password`
+    fi
+
+    if [[ -f "$AUTH_PATH/username" ]]; then
+        DB_ADMIN_USER=`cat $AUTH_PATH/username`
+    fi
+}
+
+fe_addrs=$1
+if [[ "x$fe_addrs" == "x" ]]; then
+    echo "need fe address as paramter!"
+    echo "  Example $0 <fe_addr>"
+    exit 1
+fi
+
+update_conf_from_configmap
+resolve_password_from_secret
+collect_env_info
+#add_self $fe_addr || exit $?
+check_and_register $fe_addrs
+log_stderr "run start_broker.sh"
+$DORIS_HOME/bin/start_broker.sh
diff --git a/docker/runtime/broker/resource/broker_is_alive.sh b/docker/runtime/broker/resource/broker_is_alive.sh
new file mode 100755
index 00000000000..0b55c746afa
--- /dev/null
+++ b/docker/runtime/broker/resource/broker_is_alive.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+
+log_stderr()
+{
+    echo "[`date`] $@" >&2
+}
+
+rpc_port=$1
+if [[ "x$rpc_port" == "x" ]]; then
+    echo "need broker rpc_port as paramter!"
+    exit 1
+fi
+
+netstat -nltu | grep ":$rpc_port " > /dev/null
+
+if [ $? -eq 0 ]; then
+#  log_stderr "broker ($rpc_port)alive,ProbeHandler ExecAction get exit 0"
+  exit 0
+else
+#  log_stderr "broker($rpc_port)not alive,ProbeHandler ExecAction get exit 1"
+  exit 1
+fi
diff --git a/docker/runtime/broker/resource/broker_prestop.sh b/docker/runtime/broker/resource/broker_prestop.sh
new file mode 100755
index 00000000000..a0081dec6d7
--- /dev/null
+++ b/docker/runtime/broker/resource/broker_prestop.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+DORIS_ROOT=${DORIS_ROOT:-"/opt/apache-doris"}
+DORIS_HOME=${DORIS_ROOT}/apache_hdfs_broker
+$DORIS_HOME/bin/stop_broker.sh
diff --git a/docker/runtime/broker/resource/init_broker.sh b/docker/runtime/broker/resource/init_broker.sh
index 958449d8354..7567e02e3f0 100644
--- a/docker/runtime/broker/resource/init_broker.sh
+++ b/docker/runtime/broker/resource/init_broker.sh
@@ -183,7 +183,7 @@ _main() {
   register_broker_to_fe
   check_broker_status
   doris_note "Ready to start BROKER!"
-  start_broker.sh
+  ${DORIS_HOME}/apache_hdfs_broker/bin/start_broker.sh
   exec "$@"
 }
 
diff --git a/docker/runtime/fe/Dockerfile b/docker/runtime/fe/Dockerfile
index 6ef16b9ccd7..293f72b3053 100644
--- a/docker/runtime/fe/Dockerfile
+++ b/docker/runtime/fe/Dockerfile
@@ -1,4 +1,3 @@
-#!/bin/bash
 # Licensed to the Apache Software Foundation (ASF) under one
 # or more contributor license agreements.  See the NOTICE file
 # distributed with this work for additional information
@@ -52,6 +51,11 @@ ADD resource/init_fe.sh /usr/local/bin/
 
 COPY resource/fe_*.sh /opt/apache-doris/
 
+COPY --from=selectdb/doris-debug-ubuntu:latest /doris-debug /opt/apache-doris/
+
+# when you use beijing zone, please enable the set.
+# RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
+
 WORKDIR /opt/apache-doris
 
 ENTRYPOINT ["bash","init_fe.sh"]
diff --git a/docker/runtime/fe/resource/fe_check_master.sh b/docker/runtime/fe/resource/fe_check_master.sh
new file mode 100755
index 00000000000..dfa814014a8
--- /dev/null
+++ b/docker/runtime/fe/resource/fe_check_master.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+check_first_fe_status()
+{
+    local start_time=`date +%s`
+    local expire_timeout=120
+    local helper=$1
+    while true; do
+        output=`timeout 15 mysql --connect-timeout 2 -h $helper -P $FE_QUERY_PORT -u root --skip-column-names --batch -e "SHOW FRONTENDS;"`
+    if [[ "x$output" != "x" ]]; then
+        return 0
+    fi
+
+    let "expire=start_time+expire_timeout"
+    local now=`date +%s`
+    if [[ $expire -le $now ]]; then
+        echo "[`date`] the first container is not started" >& 2
+        exit 1
+    fi
+
+    sleep 2
+    done
+}
+
+check_first_fe_status $1
+
diff --git a/docker/runtime/fe/resource/fe_entrypoint.sh b/docker/runtime/fe/resource/fe_entrypoint.sh
new file mode 100755
index 00000000000..16db02aa571
--- /dev/null
+++ b/docker/runtime/fe/resource/fe_entrypoint.sh
@@ -0,0 +1,395 @@
+#!/bin/bash
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+DORIS_ROOT=${DORIS_ROOT:-"/opt/apache-doris"}
+# if config secret for basic auth about operate node of doris, the path must be `/etc/doris/basic_auth`. This is set by operator and the key of password must be `password`.
+AUTH_PATH="/etc/basic_auth"
+# annotations_for_recovery_start
+ANNOTATION_PATH="/etc/podinfo/annotations"
+RECOVERY_KEY=""
+# fe location
+DORIS_HOME=${DORIS_ROOT}/fe
+# participant election number of fe.
+ELECT_NUMBER=${ELECT_NUMBER:=3}
+# query port for mysql connection.
+QUERY_PORT=${FE_QUERY_PORT:-9030}
+EDIT_LOG_PORT=9010
+# location of fe config store.
+FE_CONFFILE=$DORIS_HOME/conf/fe.conf
+# represents the type for fe communication: domain or IP.
+START_TYPE=
+# the master node in fe cluster.
+FE_MASTER=
+# pod ordinal of statefulset deployed pod.
+POD_INDEX=
+# probe interval: 2 seconds
+PROBE_INTERVAL=2
+# timeout for probe master: 60 seconds
+PROBE_MASTER_POD0_TIMEOUT=60 # at most 30 attempts, no less than the times needed for an election
+# no-0 ordinal pod timeout for probe master: 90 times
+PROBE_MASTER_PODX_TIMEOUT=180 # at most 90 attempts
+# administrator for administrate the cluster.
+DB_ADMIN_USER=${USER:-"root"}
+
+DB_ADMIN_PASSWD=$PASSWD
+# myself as IP or FQDN
+MYSELF=
+
+function log_stderr()
+{
+  echo "[`date`] $@" >& 2
+}
+
+#parse the `$FE_CONFFILE` file, passing the key need resolve as parameter.
+parse_confval_from_fe_conf()
+{
+    # a naive script to grep given confkey from fe conf file
+    # assume conf format: ^\s*<key>\s*=\s*<value>\s*$
+    local confkey=$1
+    local confvalue=`grep "\<$confkey\>" $FE_CONFFILE | grep -v '^\s*#' | sed 's|^\s*'$confkey'\s*=\s*\(.*\)\s*$|\1|g'`
+    echo "$confvalue"
+}
+
+# when image exist int doris-meta, use exist meta to start.
+function start_fe_with_meta()
+{
+    log_stderr "start with meta run start_fe.sh"
+    # the server will start in the current terminal session, and the log output and console interaction will be printed to that terminal
+    # befor doris 2.0.2 ,doris start with : start_xx.sh
+    # sine doris 2.0.2 ,doris start with : start_xx.sh --console  doc: https://doris.apache.org/docs/dev/install/standard-deployment/#version--202
+    $DORIS_HOME/fe/bin/start_fe.sh --console
+}
+
+collect_env_info()
+{
+    # set POD_IP, POD_FQDN, POD_INDEX, EDIT_LOG_PORT, QUERY_PORT
+    if [[ "x$POD_IP" == "x" ]] ; then
+        POD_IP=`hostname -i | awk '{print $1}'`
+    fi
+
+    if [[ "x$POD_FQDN" == "x" ]] ; then
+        POD_FQDN=`hostname -f`
+    fi
+
+    # example: fe-sr-deploy-1.fe-svc.kc-sr.svc.cluster.local
+    POD_INDEX=`echo $POD_FQDN | awk -F'.' '{print $1}' | awk -F'-' '{print $NF}'`
+
+    # since selectdb/doris.fe-ubuntu:2.0.2 , fqdn is forced to open without using ip method(enable_fqdn_mode = true).
+    # Therefore START_TYPE is true
+    START_TYPE=`parse_confval_from_fe_conf "enable_fqdn_mode"`
+
+    if [[ "x$START_TYPE" == "xtrue" ]]; then
+        MYSELF=$POD_FQDN
+    else
+        MYSELF=$POD_IP
+    fi
+
+    # edit_log_port from conf file
+    local edit_log_port=`parse_confval_from_fe_conf "edit_log_port"`
+    if [[ "x$edit_log_port" != "x" ]] ; then
+        EDIT_LOG_PORT=$edit_log_port
+    fi
+
+    # query_port from conf file
+    local query_port=`parse_confval_from_fe_conf "query_port"`
+    if [[ "x$query_port" != "x" ]] ; then
+        QUERY_PORT=$query_port
+    fi
+}
+
+# get all registered fe in cluster.
+function show_frontends()
+{
+    local addr=$1
+    # fist start use root and no password check. avoid use pre setted username and password.
+    frontends=`timeout 15 mysql --connect-timeout 2 -h $addr -P $QUERY_PORT -uroot --batch -e 'show frontends;' 2>&1`
+    log_stderr "[info] use root no password show frotends result '$frontends'"
+    if echo $frontends | grep -w "1045" | grep -q -w "28000" &>/dev/null ; then
+        log_stderr "[info] use username and password that configured show frontends."
+        frontends=`timeout 15 mysql --connect-timeout 2 -h $addr -P $QUERY_PORT -u$DB_ADMIN_USER -p$DB_ADMIN_PASSWD --batch -e 'show frontends;' 2>&1`
+    fi
+   echo "$frontends"
+
+    #if [[ "x$DB_ADMIN_PASSWD" != "x" ]]; then
+    #    timeout 15 mysql --connect-timeout 2 -h $addr -P $QUERY_PORT -u$DB_ADMIN_USER -p$DB_ADMIN_PASSWD --batch -e 'show frontends;'
+    #else
+    #    timeout 15 mysql --connect-timeout 2 -h $addr -P $QUERY_PORT -u$DB_ADMIN_USER --batch -e 'show frontends;'
+    #fi
+}
+
+# add myself in cluster for FOLLOWER.
+function add_self_follower()
+{
+    add_result=`mysql --connect-timeout 2 -h $FE_MASTER -P $QUERY_PORT -uroot --skip-column-names --batch -e "ALTER SYSTEM ADD FOLLOWER \"$MYSELF:$EDIT_LOG_PORT\";" 2>&1`
+    log_stderr "[info] use root no password to add follower result '$add_result'"
+    if echo $add_result | grep -w "1045" | grep -q -w "28000" &>/dev/null ; then
+        log_stderr "[info] use username and password that configured to add self as follower."
+        mysql --connect-timeout 2 -h $FE_MASTER -P $QUERY_PORT -u$DB_ADMIN_USER -p$DB_ADMIN_PASSWD --skip-column-names --batch -e "ALTER SYSTEM ADD FOLLOWER \"$MYSELF:$EDIT_LOG_PORT\";"
+    fi
+
+    #if [[ "x$DB_ADMIN_PASSWD" != "x" ]]; then
+    #    mysql --connect-timeout 2 -h $FE_MASTER -P $QUERY_PORT -u$DB_ADMIN_USER -p$DB_ADMIN_PASSWD --skip-column-names --batch -e "ALTER SYSTEM ADD FOLLOWER \"$MYSELF:$EDIT_LOG_PORT\";"
+    #else
+    #    mysql --connect-timeout 2 -h $FE_MASTER -P $QUERY_PORT -u$DB_ADMIN_USER --skip-column-names --batch -e "ALTER SYSTEM ADD FOLLOWER \"$MYSELF:$EDIT_LOG_PORT\";"
+    #fi
+}
+
+# add myself in cluster for OBSERVER.
+function add_self_observer()
+{
+    add_result=`mysql --connect-timeout 2 -h $FE_MASTER -P $QUERY_PORT -uroot --skip-column-names --batch -e "ALTER SYSTEM ADD OBSERVER \"$MYSELF:$EDIT_LOG_PORT\";" 2>&1`
+    log_stderr "[info] use root no password to add self as observer result '$add_result'."
+    if echo $add_result | grep -w "1045" | grep -q -w "28000" &>/dev/null ; then
+        log_stderr "[info] use username and password that configed to add self as observer."
+        mysql --connect-timeout 2 -h $FE_MASTER -P $QUERY_PORT -u$DB_ADMIN_USER -p$DB_ADMIN_PASSWD --skip-column-names --batch -e "ALTER SYSTEM ADD OBSERVER \"$MYSELF:$EDIT_LOG_PORT\";"
+    fi
+
+    #if [[ "x$DB_ADMIN_PASSWD" != "x" ]]; then
+    #    mysql --connect-timeout 2 -h $FE_MASTER -P $QUERY_PORT -u$DB_ADMIN_USER -p$DB_ADMIN_PASSWD --skip-column-names --batch -e "ALTER SYSTEM ADD OBSERVER \"$MYSELF:$EDIT_LOG_PORT\";"
+    #else
+    #    mysql --connect-timeout 2 -h $FE_MASTER -P $QUERY_PORT -u$DB_ADMIN_USER --skip-column-names --batch -e "ALTER SYSTEM ADD OBSERVER \"$MYSELF:$EDIT_LOG_PORT\";"
+    #fi
+}
+
+# `dori-meta/image` not exist start as first time.
+function start_fe_no_meta()
+{
+    # the server will start in the current terminal session, and the log output and console interaction will be printed to that terminal
+    # befor doris 2.0.2 ,doris start with : start_xx.sh
+    # sine doris 2.0.2 ,doris start with : start_xx.sh --console  doc: https://doris.apache.org/docs/dev/install/standard-deployment/#version--202
+    local opts="--console"
+    local start=`date +%s`
+    local has_member=false
+    local member_list=
+    if [[ "x$FE_MASTER" != "x" ]] ; then
+        opts+=" --helper $FE_MASTER:$EDIT_LOG_PORT"
+        local start=`date +%s`
+        while true
+        do
+            # for statefulset manage fe pods, when `ELECT_NUMBER` greater than `POD_INDEX`
+            if [[ ELECT_NUMBER -gt $POD_INDEX ]]; then
+                log_stderr "Add myself($MYSELF:$EDIT_LOG_PORT) to master as follower ..."
+                add_self_follower
+            else
+                log_stderr "Add myself($MYSELF:$EDIT_LOG_PORT) to master as observer ..."
+                add_self_observer
+            fi
+               # if successfully exit circulate register logic and start fe.
+            if show_frontends $addr | grep -q -w "$MYSELF" &>/dev/null ; then
+                break;
+            fi
+
+            local now=`date +%s`
+            let "expire=start+30" # 30s timeout
+            # if timeout for register self exit 1.
+            if [[ $expire -le $now ]] ; then
+                log_stderr "Timed out, abort!"
+                exit 1
+            fi
+
+            log_stderr "Sleep a while and retry adding ..."
+            sleep $PROBE_INTERVAL
+        done
+    fi
+    log_stderr "first start with no meta run start_fe.sh with additional options: '$opts'"
+    $DORIS_HOME/bin/start_fe.sh $opts
+}
+
+# the ordinal is 0, probe timeout as 60s, when have not meta and not `MASTER` in fe cluster, 0 start as master.
+probe_master_for_pod()
+{
+    # possible to have no result at all, because myself is the first FE instance in the cluster
+    local svc=$1
+    local start=`date +%s`
+    local has_member=false
+    local memlist=
+    while true
+    do
+        memlist=`show_frontends $svc`
+        # find master by column `IsMaster`
+        local pos=`echo "$memlist" | grep '\<IsMaster\>' | awk -F '\t' '{for(i=1;i<NF;i++) {if ($i == "IsMaster") print i}}'`
+        local master=`echo "$memlist" | grep '\<FOLLOWER\>' | awk -v p="$pos" -F '\t' '{if ($p=="true") print $2}'`
+
+        log_stderr "'IsMaster' sequence in columns is $pos, master=$master."
+        if [[ "x$master" == "x" ]]; then
+            log_stderr "[info] resolve the eighth column for finding master !"
+            master=`echo "$memlist" | grep '\<FOLLOWER\>' | awk -F '\t' '{if ($8=="true") print $2}'`
+        fi
+
+        if [[ "x$master" == "x" ]]; then
+           # compatible 2.1.0
+           log_stderr "[info] resoluve the ninth column for finding master!"
+           master=`echo "$memlist" | grep '\<FOLLOWER\>' | awk -F '\t' '{if ($9=="true") print $2}'`
+        fi
+
+        if [[ "x$master" != "x" ]] ; then
+            # has master, done
+            log_stderr "Find master: $master!"
+            FE_MASTER=$master
+            return 0
+        fi
+
+        # show frontens has members
+        if [[ "x$memlist" != "x" && "x$pos" != "x" ]] ; then
+            # has member list ever before
+            has_member=true
+        fi
+
+        # no master yet, check if needs timeout and quit
+        log_stderr "[info] master is not elected, has_member: $has_member, this may be first start or master changing, wait $PROBE_INTERVAL s to next probe..."
+        local timeout=$PROBE_MASTER_POD0_TIMEOUT
+        if  "$has_member" == true || [ "$POD_INDEX" -ne "0" ] ; then
+            # set timeout to the same as PODX since there are other members
+            timeout=$PROBE_MASTER_PODX_TIMEOUT
+        fi
+
+        local now=`date +%s`
+        let "expire=start+timeout"
+        if [[ $expire -le $now ]] ; then
+            log_stderr "[info]  exit probe master for probing timeout, if it is the first pod will start as master. .."
+            # empty FE_MASTER
+            FE_MASTER=""
+            return 0
+        fi
+        sleep $PROBE_INTERVAL
+    done
+}
+
+# when not meta exist, fe start should probe
+probe_master()
+{
+    local svc=$1
+    # resolve svc as array.
+    local addArr=${svc//,/ }
+    for addr in ${addArr[@]}
+    do
+        # if have master break for register or check.
+        if [[ "x$FE_MASTER" != "x" ]]; then
+            break
+        fi
+
+        # find master under current service and set to FE_MASTER
+        probe_master_for_pod $addr
+    done
+
+    # if first pod assume first start should as master. others first start have not master exit.
+    if [[ "x$FE_MASTER" == "x" ]]; then
+        if [[ "$POD_INDEX" -eq 0 ]]; then
+            return 0
+        else
+            log_stderr "the pod can't connect to pod 0, the network may be not work. please verify domain connectivity with two pods in different node and verify the pod 0 ready or not."
+            exit 1
+        fi
+    fi
+}
+
+function add_fqdn_config()
+{
+    # TODO(user):since selectdb/doris.fe-ubuntu:2.0.2 , `enable_fqdn_mode` is forced to set `true` for starting doris. (enable_fqdn_mode = true).
+    local enable_fqdn=`parse_confval_from_fe_conf "enable_fqdn_mode"`
+    log_stderr "enable_fqdn is : $enable_fqdn"
+    if [[ "x$enable_fqdn" != "xtrue" ]] ; then
+        log_stderr "add enable_fqdn_mode = true to ${DORIS_HOME}/conf/fe.conf"
+        echo "enable_fqdn_mode = true" >>${DORIS_HOME}/conf/fe.conf
+    fi
+}
+
+update_conf_from_configmap()
+{
+    if [[ "x$CONFIGMAP_MOUNT_PATH" == "x" ]] ; then
+        log_stderr '[info] Empty $CONFIGMAP_MOUNT_PATH env var, skip it!'
+        add_fqdn_config
+        return 0
+    fi
+    if ! test -d $CONFIGMAP_MOUNT_PATH ; then
+        log_stderr "[info] $CONFIGMAP_MOUNT_PATH not exist or not a directory, ignore ..."
+        add_fqdn_config
+        return 0
+    fi
+    local tgtconfdir=$DORIS_HOME/conf
+    for conffile in `ls $CONFIGMAP_MOUNT_PATH`
+    do
+        log_stderr "[info] Process conf file $conffile ..."
+        local tgt=$tgtconfdir/$conffile
+        if test -e $tgt ; then
+            # make a backup
+            mv -f $tgt ${tgt}.bak
+        fi
+        ln -sfT $CONFIGMAP_MOUNT_PATH/$conffile $tgt
+    done
+    add_fqdn_config
+}
+
+# resolve password for root
+resolve_password_from_secret()
+{
+    if [[ -f "$AUTH_PATH/password" ]]; then
+        DB_ADMIN_PASSWD=`cat $AUTH_PATH/password`
+    fi
+
+    if [[ -f "$AUTH_PATH/username" ]]; then
+        DB_ADMIN_USER=`cat $AUTH_PATH/username`
+    fi
+}
+
+start_fe_with_meta()
+{
+    # the server will start in the current terminal session, and the log output and console interaction will be printed to that terminal
+    # befor doris 2.0.2 ,doris start with : start_xx.sh
+    local opts="--console"
+    local recovery=`grep "\<selectdb.com.doris/recovery\>" $ANNOTATION_PATH | grep -v '^\s*#' | sed 's|^\s*'$confkey'\s*=\s*\(.*\)\s*$|\1|g'`
+    if [[ "x$recovery" != "x" ]]; then
+        opts=${opts}" --metadata_failure_recovery"
+    fi
+
+    log_stderr "start with meta run start_fe.sh with additional options: '$opts'"
+     # sine doris 2.0.2 ,doris start with : start_xx.sh --console  doc: https://doris.apache.org/docs/dev/install/standard-deployment/#version--202
+    $DORIS_HOME/bin/start_fe.sh  $opts
+}
+
+print_vlsn()
+{
+    local doirs_meta_path=`parse_confval_from_fe_conf "meta_dir"`
+    if [[ "x$doirs_meta_path" == "x" ]] ; then
+        doris_meta_path="/opt/apache-doris/fe/doris-meta"
+    fi
+
+    vlsns=`grep -rn "VLSN:" $doris_meta_path/bdb/je* | tail -n 10`
+    echo "$vlsns"
+}
+
+fe_addrs=$1
+if [[ "x$fe_addrs" == "x" ]]; then
+    echo "need fe address as parameter!"
+    exit
+fi
+
+update_conf_from_configmap
+# resolve password for root to manage nodes in doris.
+resolve_password_from_secret
+if [[ -f "/opt/apache-doris/fe/doris-meta/image/ROLE" ]]; then
+    log_stderr "start fe with exist meta."
+    ./doris-debug --component fe
+    print_vlsn
+    start_fe_with_meta
+else
+    log_stderr "first start fe with meta not exist."
+    collect_env_info
+    probe_master $fe_addrs
+    start_fe_no_meta
+fi
diff --git a/docker/runtime/fe/resource/fe_prestop.sh b/docker/runtime/fe/resource/fe_prestop.sh
new file mode 100755
index 00000000000..4a2eb59df90
--- /dev/null
+++ b/docker/runtime/fe/resource/fe_prestop.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+DORIS_ROOT=${DORIS_ROOT:-"/opt/apache-doris"}
+DORIS_HOME=${DORIS_ROOT}/fe
+$DORIS_HOME/bin/stop_fe.sh
diff --git a/docker/runtime/fe/resource/init_fe.sh b/docker/runtime/fe/resource/init_fe.sh
index c1e1a2c282b..8cbd80ea237 100644
--- a/docker/runtime/fe/resource/init_fe.sh
+++ b/docker/runtime/fe/resource/init_fe.sh
@@ -295,7 +295,7 @@ _main() {
     docker_required_variables_env
     trap 'cleanup' SIGTERM SIGINT
     if [[ $RUN_TYPE == "K8S" ]]; then
-        start_fe.sh --console &
+        ${DORIS_HOME}/fe/bin/start_fe.sh --console &
         child_pid=$!
     else
         docker_setup_env
@@ -310,10 +310,10 @@ _main() {
         doris_note "Ready to start CURRENT_FE!"
 
         if [ $CURRENT_FE_IS_MASTER == true ]; then
-            start_fe.sh --console &
+            ${DORIS_HOME}/fe/bin/start_fe.sh --console &
             child_pid=$!
         else
-            start_fe.sh --helper ${MASTER_FE_IP}:${MASTER_FE_EDIT_PORT} --console &
+            ${DORIS_HOME}/fe/bin/start_fe.sh --helper ${MASTER_FE_IP}:${MASTER_FE_EDIT_PORT} --console &
             child_pid=$!
         fi
     fi


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org