Argo CD Redis パスワード生成プロセス
このドキュメントは、Argo CD を使用している際に、Redis パスワードの Secret が Helm テンプレートには存在しないにもかかわらず Secret が生成される現象について、その疑問を解決するために作成されました。
redis-secret-init
Job が argocd admin redis-initial-password
コマンドを通じてパスワードを生成することを知り、kubectl
コマンドなしでどのように Secret が作成されるのか、その内部動作を詳細に分析した結果を説明します。
Argo CD で使用される Redis の初期パスワードは、argocd admin redis-initial-password
というコマンドを通じて生成されます。このプロセスは通常、redis-secret-init
という Job によって自動的に実行され、全体の流れは以下の通りです。
-
コマンド実行: ユーザーが
argocd admin redis-initial-password
コマンドを実行します。 -
Kubernetes クラスター接続: Go 言語で書かれた
client-go
ライブラリを使用して、Kubernetes API サーバーと通信する準備をします。 -
パスワード Secret の確認:
argocd-redis-initial-password
という名前の Secret が既に存在するかを確認します。 -
パスワード生成と Secret の保存:
- 存在しない場合: 16 桁のランダムなパスワードを生成し、
password
というキーで Secret に保存します。 - 既に存在する場合: このステップをスキップし、既存の Secret をそのまま使用します。
- 存在しない場合: 16 桁のランダムなパスワードを生成し、
-
最終確認: Secret とその中の
password
キーが正しく存在するかを再度検証し、結果を出力します。
詳細プロセス: コードと関数の流れ
1段階: コマンド定義と Kubernetes フラグ設定
プログラムが開始されると、まずユーザーが入力したコマンドを処理する準備をします。
-
ファイル:
cmd/argocd/commands/admin/redis_initial_password.go
-
主要関数:
NewRedisInitialPasswordCommand()
この関数は、redis-initial-password
コマンドの名前、説明、および実行ロジックを定義します。重要な部分は、Kubernetes クラスター接続に必要な情報を受け取るために、kubectl
に似たコマンドラインフラグ(例: --kubeconfig
, --namespace
)を設定することです。
-
関連関数:
cli.AddKubectlFlagsToCmd(&command)
-
ファイル:
util/cli/cli.go
-
役割: この関数は、
client-go
ライブラリのclientcmd
パッケージを活用して、ユーザーが入力した--kubeconfig
などのフラグ値を読み取り、Kubernetes クラスター接続設定を構成するClientConfig
インターフェースを生成します。kubectl
コマンドを直接実行するのではなく、Go コード内で Kubernetes と通信する準備を完了します。
// redis_initial_password.go
func NewRedisInitialPasswordCommand() *cobra.Command {
var clientConfig clientcmd.ClientConfig
command := cobra.Command{
Use: "redis-initial-password",
Short: "Ensure the Redis password exists, creating a new one if necessary.",
Run: func(_ *cobra.Command, _ []string) {
// 2段階からのロジックがここに含まれます。
},
}
// Kubernetes接続のためのフラグを設定し、clientConfigを初期化します。
clientConfig = cli.AddKubectlFlagsToCmd(&command)
return &command
}
2段階: Kubernetes クライアントの生成
コマンドの実際の実行ロジック(Run
関数)が開始されると、1段階で準備された clientConfig
を使用して、Kubernetes API サーバーと通信できるクライアントを生成します。
-
ファイル:
cmd/argocd/commands/admin/redis_initial_password.go
- 主要コード:
// Run 関数内部
// 1. clientConfigから名前空間とクラスター接続情報を取得します。
namespace, _, err := clientConfig.Namespace()
config, err := clientConfig.ClientConfig()
// 2. 上記の情報に基づいて、実際のAPIリクエストを送信できるKubernetesクライアントを生成します。
kubeClientset := kubernetes.NewForConfigOrDie(config)
kubeClientset
オブジェクトは、Go コードで Kubernetes のリソース(Secret、Pod など)を照会、作成、変更、削除できる強力なツールとなります。
3段階: パスワード生成と Secret 作成要求
次に Redis パスワードを格納する Secret を作成します。
-
ファイル:
cmd/argocd/commands/admin/redis_initial_password.go
- 主要コード:
// 1. ランダムパスワードの生成
// generateRandomPassword() 関数は、数字、大文字小文字の英字、ハイフン(-)を組み合わせて16桁の文字列を作成します。
randomPassword, err := generateRandomPassword()
// 2. Secretオブジェクトの定義
// 生成されたパスワードを'password'キーに格納し、'argocd-redis-initial-password'という名前のSecret構造体を作成します。
secret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: common.RedisInitialCredentials, // "argocd-redis-initial-password"
Namespace: namespace,
},
Data: map[string][]byte{
common.RedisInitialCredentialsKey: []byte(randomPassword), // key: "password"
},
}
// 3. Secret作成APIの呼び出し
// 2段階で作成したkubeClientsetを使用して、KubernetesにSecret作成を要求します。
_, err = kubeClientset.CoreV1().Secrets(namespace).Create(context.Background(), secret, metav1.CreateOptions{})
// もしSecretが既に存在する場合(apierrors.IsAlreadyExists(err))、エラーとして処理せずにスキップします。
if err != nil && !apierrors.IsAlreadyExists(err) {
errors.CheckError(err)
}
4段階: 最終確認と結果出力
最後に、Secret が意図通りに正しく生成されたかを確認します。このプロセスは、Secret が元々存在していたか、新しく作成されたかに関係なく常に実行されます。
-
ファイル:
cmd/argocd/commands/admin/redis_initial_password.go
- 主要コード:
// 1. Secret取得APIの呼び出し
// Kubernetes APIサーバーに該当Secret情報を再度要求します。
secret, err = kubeClientset.CoreV1().Secrets(namespace).Get(context.Background(), redisInitialCredentials, metav1.GetOptions{})
errors.CheckError(err)
// 2. Secretデータキーの確認
// 取得したSecretのデータ内に'password'キーが存在するかを確認します。
if _, ok := secret.Data[redisInitialCredentialsKey]; ok {
fmt.Println("Password secret is configured properly.")
} else {
// キーが存在しない場合、エラーを発生させてプログラムを終了します。
errors.Fatal(errors.ErrorGeneric, fmt.Sprintf("key %s doesn't exist in secret %s.", redisInitialCredentialsKey, redisInitialCredentials))
}
このように、argocd admin redis-initial-password
コマンドは、kubectl
を直接呼び出す代わりに、client-go
ライブラリを通じて Kubernetes API と直接通信し、Redis パスワードを含む Secret を安定して生成および管理する役割を果たします。