-
Notifications
You must be signed in to change notification settings - Fork 5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[bitnami/etcd] Stop relying on files for state #75906
base: main
Are you sure you want to change the base?
Conversation
- Remove prestop logic (no longer removing member when container stops) - Remove members not included in ETCD_INITIAL_CLUSTERS during startup - Stop storing member id on a separate file, member id is checked from etcd data dir instead - Stop reading member removal state off of disk, probe the cluster instead - Remove old member (with the same name) if exist before adding new member - If data dir is not empty, check if the member still belongs to the cluster. If not, remove data dir, remove member with the same name, and add new member - Remove env var ETCD_DISABLE_STORE_MEMBER_ID - Remove env var ETCD_DISABLE_PRESTOP Signed-off-by: Khoi Pham <[email protected]>
Signed-off-by: Khoi Pham <[email protected]>
Signed-off-by: Khoi Pham <[email protected]>
Signed-off-by: Khoi Pham <[email protected]>
Signed-off-by: Khoi Pham <[email protected]>
…s new Signed-off-by: Khoi Pham <[email protected]>
I'm planning to open a complementary PR in the charts repo. I will try to add more tests there. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @pckhoi
Thanks so much for this amazing contribution! It'd definitely help on making the Bitnami etcd chart more stable.
I think the main concern/challenge with your changes would be providing a solution for users who may scale down the cluster via kubectl scale sts/etcd --replicas X
(or via some HorizontalPodAutoscaler that may also scale down the cluster without Helm's control via hooks). Correct me if I'm wrong but this use case won't be covered, right?
bitnami/etcd/3.5/debian-12/rootfs/opt/bitnami/scripts/etcd/preupgrade.sh
Outdated
Show resolved
Hide resolved
bitnami/etcd/3.5/debian-12/rootfs/opt/bitnami/scripts/etcd/preupgrade.sh
Outdated
Show resolved
Hide resolved
bitnami/etcd/3.5/debian-12/rootfs/opt/bitnami/scripts/libetcd.sh
Outdated
Show resolved
Hide resolved
@juan131 you're correct that the autoscaling use case isn't covered. People use Etcd for its consistency rather than for handling large, fluctuating traffic so I think autoscaling to handle large traffic is a niche use case. As for manual scaling, running |
Thanks for confirming so @pckhoi ! In that case, I'd add a warning at the "Upgrading" section alerting about what these changes imply (I mean, warning users to use exclusively Helm to scale the cluster): We could even add it in the chart NOTES: |
Sure, I will do that. |
Signed-off-by: Khoi Pham <[email protected]>
Signed-off-by: Khoi Pham <[email protected]>
Signed-off-by: Khoi Pham <[email protected]>
@juan131 I have updated https://github.com/bitnami/charts/tree/main/bitnami/etcd#upgrading. As for https://github.com/bitnami/charts/blob/main/bitnami/etcd/templates/NOTES.txt, I don't see anything that needs to be updated. |
# Return a comma separated list of <host>:<port> for each endpoint | ||
# Globals: | ||
# ETCD_* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
# Return a comma separated list of <host>:<port> for each endpoint | |
# Globals: | |
# ETCD_* | |
# Return a comma separated list of <host>:<port> for each endpoint | |
# based on "initial-cluster" flag value | |
# ref: https://etcd.io/docs/latest/op-guide/clustering/#static | |
# Globals: | |
# ETCD_INITIAL_CLUSTER |
######################## | ||
# Remove members that are not named in ETCD_INITIAL_CLUSTER | ||
# Globals: | ||
# ETCD_* | ||
# Arguments: | ||
# None | ||
# Returns: | ||
# None | ||
######################### | ||
remove_members() { | ||
local -a extra_flags current expected | ||
|
||
read -r -a extra_flags <<<"$(etcdctl_auth_flags)" | ||
is_boolean_yes "$ETCD_ON_K8S" && extra_flags+=("--endpoints=$(endpoints_as_host_port)") | ||
debug "Listing members" | ||
current="$(etcdctl member list ${extra_flags[@]} --write-out simple | awk -F ", " '{print $1 "," $3}')" | ||
if [ $? -ne 0 ]; then | ||
debug "Error listing members, is this a new cluster?" | ||
return 0 | ||
fi | ||
info "Current cluster members are: $(echo "${current[@]}" | awk -F, '{print $2}' | tr -s '\n' ',' | sed 's/,$//g')" | ||
|
||
expected="$(echo $ETCD_INITIAL_CLUSTER | sed 's/,/\n/g' | awk -F= '{print $1}')" | ||
info "Expected cluster members are: $(IFS= echo "${expected[@]}" | tr -s '\n' ', ' | sed 's/,$//g')" | ||
|
||
for member in $(comm -23 <(echo "${current[@]}" | awk -F, '{print $2}' | sort) <(echo "${expected[@]}" | sort)); do | ||
info "Removing obsolete member $member" | ||
etcdctl member remove ${extra_flags[@]} $(echo "${current[@]}" | grep "$member" | awk -F, '{print $1}') | ||
done | ||
} | ||
|
||
remove_members |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given this function isn't reused anywhere and it contains the actual logic of the script, I think it's simpler to directly use the code, check my suggestion:
######################## | |
# Remove members that are not named in ETCD_INITIAL_CLUSTER | |
# Globals: | |
# ETCD_* | |
# Arguments: | |
# None | |
# Returns: | |
# None | |
######################### | |
remove_members() { | |
local -a extra_flags current expected | |
read -r -a extra_flags <<<"$(etcdctl_auth_flags)" | |
is_boolean_yes "$ETCD_ON_K8S" && extra_flags+=("--endpoints=$(endpoints_as_host_port)") | |
debug "Listing members" | |
current="$(etcdctl member list ${extra_flags[@]} --write-out simple | awk -F ", " '{print $1 "," $3}')" | |
if [ $? -ne 0 ]; then | |
debug "Error listing members, is this a new cluster?" | |
return 0 | |
fi | |
info "Current cluster members are: $(echo "${current[@]}" | awk -F, '{print $2}' | tr -s '\n' ',' | sed 's/,$//g')" | |
expected="$(echo $ETCD_INITIAL_CLUSTER | sed 's/,/\n/g' | awk -F= '{print $1}')" | |
info "Expected cluster members are: $(IFS= echo "${expected[@]}" | tr -s '\n' ', ' | sed 's/,$//g')" | |
for member in $(comm -23 <(echo "${current[@]}" | awk -F, '{print $2}' | sort) <(echo "${expected[@]}" | sort)); do | |
info "Removing obsolete member $member" | |
etcdctl member remove ${extra_flags[@]} $(echo "${current[@]}" | grep "$member" | awk -F, '{print $1}') | |
done | |
} | |
remove_members | |
# Remove members that are not listed in ETCD_INITIAL_CLUSTER | |
# from the cluster before running Helm upgrades that potentially scale | |
# down the etcd cluster | |
read -r -a extra_flags <<<"$(etcdctl_auth_flags)" | |
is_boolean_yes "$ETCD_ON_K8S" && extra_flags+=("--endpoints=$(endpoints_as_host_port)") | |
debug "Listing members" | |
if ! current="$(etcdctl member list ${extra_flags[@]} --write-out simple | awk -F ", " '{print $3 ":" $1}')"; then | |
debug "Error listing members, is this a new cluster?" | |
return 0 | |
fi | |
info "Current cluster members are: $(echo "$current" | awk -F: '{print $1}' | tr -s '\n' ',' | sed 's/,$//g')" | |
expected="$(echo $ETCD_INITIAL_CLUSTER | tr -s ',' '\n' | awk -F= '{print $1}')" | |
info "Expected cluster members are: $(echo "$expected" | tr -s '\n' ',' | sed 's/,$//g')" | |
for member in $(comm -23 <(echo "$current" | awk -F: '{print $1}' | sort) <(echo "$expected" | sort)); do | |
info "Removing obsolete member $member" | |
etcdctl member remove ${extra_flags[@]} "$(echo "$current" | grep "$member" | awk -F: '{print $2}')" | |
done |
if ! etcdctl endpoint status --cluster ${extra_flags[@]}; then | ||
return 0 | ||
else | ||
return 1 | ||
fi |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shorter:
if ! etcdctl endpoint status --cluster ${extra_flags[@]}; then | |
return 0 | |
else | |
return 1 | |
fi | |
! debug_execute etcdctl endpoint status --cluster ${extra_flags[@]} |
bitnami/etcd/README.md
Outdated
|
||
Additionally, you can configure etcd using the upstream env variables [here](https://etcd.io/docs/v3.4/op-guide/configuration/) | ||
|
||
## Notable Changes | ||
|
||
### 3.5.17-debian-12-r3 | ||
|
||
* Drop support for non-Helm deployment. Upgrading of any kind including increasing replica count must also be done with `helm upgrade` exclusively. CD automation tools that respect Helm hooks such as ArgoCD can also be used. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* Drop support for non-Helm deployment. Upgrading of any kind including increasing replica count must also be done with `helm upgrade` exclusively. CD automation tools that respect Helm hooks such as ArgoCD can also be used. | |
* Drop support for non-Helm cluster deployment. Upgrading of any kind including increasing replica count must also be done with `helm upgrade` exclusively. CD automation tools that respect Helm hooks such as ArgoCD can also be used. |
| `ETCD_NEW_MEMBERS_ENV_FILE` | File containining the etcd environment to use after adding a member. | `${ETCD_DATA_DIR}/new_member_envs` | | ||
| `ETCD_DAEMON_USER` | etcd system user name. | `etcd` | | ||
| `ETCD_DAEMON_GROUP` | etcd system user group. | `etcd` | | ||
| `ETCD_INITIAL_CLUSTER_STATE` | Initial cluster state. Either "new" or "existing". | `nil` | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this still used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The user does not use it. Is it fine to leave it in the read-only section then?
Signed-off-by: Khoi Pham <[email protected]>
Thanks! I have addressed all the suggestsions. |
Description of the change
The current etcd container and chart have a few major problems:
replicas
update then the next time the pod starts, it will not be able to start from the existing data dir which means it must throw away the data dir and start from scratch.etcdctl member update
for unclear reasons when the data dir is not empty and there is a member IDETCD_INITIAL_CLUSTER_STATE
to know whether the cluster is new which could be inaccurateThis PR add the following changes:
preupgrade.sh
which should be run in a Helm pre-upgrade hook. When the cluster is scaled down, it detects and removes obsolete members withetcdctl member remove
.prestop.sh
member_id
file. Instead, the remote member ID is read from the cluster withetcdctl member list
, and the local member ID is checked for conflict during startup.member_removal.log
. Check withetcdctl member list
instead.ETCD_DISABLE_STORE_MEMBER_ID
ETCD_DISABLE_PRESTOP
ETCD_INITIAL_CLUSTER_STATE
becomes read-onlyBenefits
etcdctl member remove
command tends to be executed against a healthy clusterPossible drawbacks
Applicable issues
Additional information
Related changes in the Helm chart: bitnami/charts#31161 and bitnami/charts#31164