Skip to content

Instantly share code, notes, and snippets.

@JanHolger
Last active May 16, 2025 14:44
Show Gist options
  • Save JanHolger/c2bcdba384ca48fb843005f7264b6896 to your computer and use it in GitHub Desktop.
Save JanHolger/c2bcdba384ca48fb843005f7264b6896 to your computer and use it in GitHub Desktop.
Migrate etcd -> kine and kine -> etcd
# !!!!!!!!!!!!!!!!!!!!
# Before using this script stop the apiserver and ensure that there are no leases (etcdctl lease list). If there are any leases, revoke them first.
# !!!!!!!!!!!!!!!!!!!!
# You may need to: export PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python
import etcd3
# Replace with your etcd instance
from_client = etcd3.client(
host="127.0.0.1",
port=2379,
ca_cert="/etc/kubernetes/pki/etcd/ca.crt",
cert_cert="/etc/kubernetes/pki/etcd/peer.crt",
cert_key="/etc/kubernetes/pki/etcd/peer.key",
grpc_options=[
('grpc.max_receive_message_length', 1000000000)
]
)
# Replace with your kine instance
to_client = etcd3.client(
host="127.0.0.1",
port=2479
)
keys = from_client.get_all()
for k in keys:
(value, meta) = k
# Since kine doesn't actually implement the etcd protocol, just very specificly constructed calls, we need to build this weird transaction instead of just calling put
# Reference: https://github.com/k3s-io/kine/blob/master/pkg/server/update.go#L9
to_client.transaction(
compare=[
to_client.transactions.mod(meta.key) == 0
],
success=[
to_client.transactions.put(meta.key, value)
],
failure=[
to_client.transactions.get(meta.key)
]
)
# You may need to: export PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python
import etcd3
# Before using this script stop the apiserver. Also ensure that the target etcd cluster is clean
# Replace with your kine instance
from_client = etcd3.client(
host="127.0.0.1",
port=2479
)
# Replace with your etcd instance
to_client = etcd3.client(
host="127.0.0.1",
port=2379,
ca_cert="/etc/kubernetes/pki/etcd/ca.crt",
cert_cert="/etc/kubernetes/pki/etcd/peer.crt",
cert_key="/etc/kubernetes/pki/etcd/peer.key"
)
# Since using an empty prefix will produce an invalid SQL query, we need to use a prefix here instead
prefix="/"
keys = from_client.get_range(prefix.encode(), etcd3.utils.increment_last_byte(prefix.encode()))
for k in keys:
(value, meta) = k
to_client.transaction(
compare=[
to_client.transactions.mod(meta.key) == 0
],
success=[
to_client.transactions.put(meta.key, value)
],
failure=[
to_client.transactions.get(meta.key)
]
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment