ICTSC2025 一次予選 問題解説: 問32 - 問35
問32
ictsc-app
という名前のアプリ開発をDockerコンテナを用いて行っている。開発中、動作確認のために docker run
コマンドでアプリケーションを立ち上げたところ、何のエラーメッセージも残さず、すぐに終了してしまった。
このままでは原因の特定が困難であるため、デバッグのために sleep
コマンドでコンテナを立ち上げたままにしておいて、手動でアプリケーションの起動を行うことにした。
早速、以下のコマンドを用いてデバッグを行ったところ、想定とは異なり、何のエラーメッセージも残さず、すぐにコンテナが終了してしまった。
$ docker run ictsc-app sleep infinity
<何のエラーも表示されない>
$
参考として、ictsc-app
のイメージの inspect
結果を以下に記載する。
[
{
"Id": "sha256:fbf43b316565127503a3dfd8b91555ee90b8e0c45253b6c662bfba0980d67d7b",
"RepoTags": [
"ictsc-app:latest"
],
"RepoDigests": [],
"Parent": "",
"Comment": "buildkit.dockerfile.v0",
"Created": "2025-07-20T12:36:39.693337178Z",
"DockerVersion": "",
"Author": "",
"Architecture": "amd64",
"Os": "linux",
"Size": 228891807,
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/zkni6b0f322qj7fbxf6vuqbl8/diff:/var/lib/docker/overlay2/evianeisobabny0hal63mfxkz/diff:/var/lib/docker/overlay2/v77bsu7awo1rc0g9jzee6a2ay/diff:/var/lib/docker/overlay2/xrw3obhyses63qxii0d16wz0n/diff:/var/lib/docker/overlay2/f16r4zgulg80u238s6jt4qllc/diff:/var/lib/docker/overlay2/a75173256e30d32a5924d904e3374f744a9b963330f3d03a07c507f6f4fbc7db/diff:/var/lib/docker/overlay2/67c6bcfeecdf156a1846805cffa104cd1638abd9c3cc0719977799f5cfc3c7c3/diff:/var/lib/docker/overlay2/b24eab56679a9d8d52fe510a171d2f0ff6722f8ebb8816fa87bfca0adec04f15/diff:/var/lib/docker/overlay2/9e5ff3b7938c82f17e782093a275b1d27ef5357fd5543a73e07e87727eb7e914/diff:/var/lib/docker/overlay2/700e9b1d337627e508de8474fd308b441c697c9cff16f74f4fe9b0b0950f4f85/diff",
"MergedDir": "/var/lib/docker/overlay2/xw56bqt5n6mpbt9rwaivv76m4/merged",
"UpperDir": "/var/lib/docker/overlay2/xw56bqt5n6mpbt9rwaivv76m4/diff",
"WorkDir": "/var/lib/docker/overlay2/xw56bqt5n6mpbt9rwaivv76m4/work"
},
"Name": "overlay2"
},
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:1bb35e8b4de116e84b2ccf614cce4e309b6043bf2cd35543d8394edeaeb587e3",
"sha256:f812e127e0f9a0d7faa4adbd6e7d873e42ebcff11d259072ae50b6352c974c70",
"sha256:ffb20e72f4439a0a3cd15016f88ff96b70f32cecce8e2ed9e7301da32930246b",
"sha256:67d8d621bc8be2ed5ef4e017e4237ebecf2f51e3048537b940cabf4e3c3cfcd2",
"sha256:f3acd5c28703efcaf432602c2054b6761fc20576320b1e4de0130f9dc485b239",
"sha256:53349f3b3db7206e7377bf0a02fe93a67004a66b0be4846616fdc8957116a74c",
"sha256:e7e841982c20b39ccdbd3ee8487abb88c5c00cf5d191442f44d3331c2c6560e0",
"sha256:2b18ef3e69e1be7619ddbfbbf8cf281d4256bd3d7b02d7401fddf43e9d10d62b",
"sha256:f59971410f3f5df177c7c0b2e77b46f1db88fd663a1c072f28b909ce44a6922b",
"sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef",
"sha256:135a92f6fd34095609ae87227871a54768ab89e08b234dd3b285b85456b5d7a6"
]
},
"Metadata": {
"LastTagTime": "2025-07-20T12:36:39.859733108Z"
},
"Config": {
"Cmd": null,
"Entrypoint": [
"node",
"./index.js"
],
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"NODE_VERSION=22.17.1",
"YARN_VERSION=1.22.22"
],
"ExposedPorts": {
"3001/tcp": {}
},
"Labels": null,
"OnBuild": null,
"User": "",
"Volumes": null,
"WorkingDir": "/app"
}
}
]
コンテナが終了してしまう原因として最も適当なものを1つ選べ。
選択肢(択一選択)
ictsc-app
イメージ内にsleep
コマンドが存在しないsleep
コマンドが、コンテナの起動時に実行されるイメージで指定されているコマンドによって上書きされてしまったsleep
コマンドが、コンテナ起動時に実行されるイメージで指定されているコマンドの引数として解釈されてしまったsleep
コマンドがバックグラウンドで実行されてしまった
正解
3
解説
正解は 3 の 「sleep
コマンドが、コンテナ起動時に実行されるイメージで指定されているコマンドの引数として解釈されてしまった」
(句点をつけ忘れてしまい、めちゃくちゃ読みづらい選択肢になってしまったことを反省しています)
Docker コンテナの ENTRYPOINT
と CMD
の組み合わせに関して問う問題でした。
- 「コンテナ起動時に実行されるイメージで指定されているコマンド」= ENTRYPOINT
- 「コマンドの引数」= CMD
という意味でした。
ENTRYPOINT
と CMD
はコンテナ実行時に実行されるコマンド文字列を指定する命令ですが、両方を同時にしていを指定すると、CMD
で指定された文字列は ENTRYPOINT
の引数として評価されます。
また、docker run
コマンドの引数として指定した文字列(オプション以外。今回の問題で言えば sleep infinity
のところ)は CMD
として評価されます。
与えられた inspect 結果をよく見てみると、ENTRYPOINT
として node ./index.js
が渡されているため、docker run sleep infinity
を実行すると、コンテナ内部では node ./index.js sleep infinity
として実行されます。
sleep
コマンドを指定したが、node
コマンドの引数として評価されてしまったのでコンテナがすぐに終了してしまったというわけです。
他の選択肢が除外できる理由は以下の通りです
-
ictsc-app
イメージ内にsleep
コマンドが存在しない
- もし
sleep
コマンドを正しく指定できており、なおかつsleep
コマンドが存在しない場合は、そのようなエラーメッセージが出るはずです。
-
sleep
コマンドが、コンテナの起動時に実行されるイメージで指定されているコマンドによって上書きされてしまった
CMD
が元々指定されているイメージに、ENTRYPOINT
で上書き(正確には、引数としてしまう)することはできますが、逆はできません。
-
sleep
コマンドがバックグラウンドで実行されてしまった
- バックグラウンド実行を行う指定を一切していないので不適です。
-
参考: https://docs.docker.jp/v1.12/engine/reference/builder.html#cmd-entrypoint
問33
以下のような構成でローカルネットワークを構築した(この図に記載されているもの以外のサーバやネットワーク機器はない)。
+---------------------------+ +---------------------------+
| Host1 | | Host2 |
| | | |
| IP(eth1): 192.168.0.1/24 | | IP(eth1): 192.168.0.2/24 |
| Nameserver: 192.168.0.254 | | Nameserver: 192.168.0.10 |
| Route: | | Route: |
| default via192.168.0.254 | | default via192.168.0.254 |
+---------------------------+ +---------------------------+
|(eth1) |(eth1)
+------------------+-----------------+
|(eth1)
+----------------------------+
| Router(Default GW) |
| |
| IP(eth1): 192.168.0.254/24 |
| 提供サービス: DNS Resolver |
+----------------------------+
このネットワーク上で、Host1 から Host2 へ SSH 接続を行ったところ、接続に5秒程度時間がかかった。普段であれば、1秒以内に接続できるのだが、どうやら Host2 の sshd_config
を変更した後から、5秒程度かかるようになってしまった。
以下は Host2 の sshd_config
である。
# This is the sshd server system-wide configuration file. See
# sshd_config(5) for more information.
# This sshd was compiled with PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
# The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
# possible, but leave them commented. Uncommented options override the
# default value.
Port 22
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::
#HostKey /etc/ssh/ssh_host_rsa_key
#HostKey /etc/ssh/ssh_host_ecdsa_key
#HostKey /etc/ssh/ssh_host_ed25519_key
# Ciphers and keying
#RekeyLimit default none
# Logging
#SyslogFacility AUTH
LogLevel INFO
# Authentication:
#LoginGraceTime 2m
#PermitRootLogin prohibit-password
#StrictModes yes
MaxAuthTries 6
MaxSessions 10
#PubkeyAuthentication yes
# Expect .ssh/authorized_keys2 to be disregarded by default in future.
#AuthorizedKeysFile .ssh/authorized_keys .ssh/authorized_keys2
#AuthorizedPrincipalsFile none
#AuthorizedKeysCommand none
#AuthorizedKeysCommandUser nobody
# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
#HostbasedAuthentication no
# Change to yes if you don't trust ~/.ssh/known_hosts for
# HostbasedAuthentication
#IgnoreUserKnownHosts no
# Don't read the user's ~/.rhosts and ~/.shosts files
#IgnoreRhosts yes
# To disable tunneled clear text passwords, change to no here!
PasswordAuthentication no
PermitEmptyPasswords no
# Change to yes to enable challenge-response passwords (beware issues with
# some PAM modules and threads)
KbdInteractiveAuthentication no
# Kerberos options
#KerberosAuthentication no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes
#KerberosGetAFSToken no
# GSSAPI options
#GSSAPIAuthentication no
#GSSAPICleanupCredentials yes
#GSSAPIStrictAcceptorCheck yes
#GSSAPIKeyExchange no
# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
# be allowed through the KbdInteractiveAuthentication and
# PasswordAuthentication. Depending on your PAM configuration,
# PAM authentication via KbdInteractiveAuthentication may bypass
# the setting of "PermitRootLogin without-password".
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and KbdInteractiveAuthentication to 'no'.
UsePAM no
AllowAgentForwarding yes
AllowTcpForwarding yes
GatewayPorts no
X11Forwarding yes
#X11DisplayOffset 10
#X11UseLocalhost yes
#PermitTTY yes
PrintMotd no
PrintLastLog yes
TCPKeepAlive yes
#PermitUserEnvironment no
#Compression delayed
#ClientAliveInterval 0
#ClientAliveCountMax 3
UseDNS yes
#PidFile /run/sshd.pid
#MaxStartups 10:30:100
#PermitTunnel no
#ChrootDirectory none
#VersionAddendum none
# no default banner path
#Banner none
# Allow client to pass locale environment variables
AcceptEnv LANG LC_*
# override default of no subsystems
Subsystem sftp /usr/lib/openssh/sftp-server
# Example of overriding settings on a per-user basis
#Match User anoncvs
# X11Forwarding no
# AllowTcpForwarding no
# PermitTTY no
# ForceCommand cvs server
以下の文はこの問題の解決法をを記している。[X] と [Y] を適切な単語で補い文を完成させよ。
sshd_config
の [X] の設定を [Y] にし、Host2 のsshd
を再起動する
正解
sshd_config
の [useDNS] の設定を [no] にし、Host2 の sshd
を再起動する
解説
sshd
の useDNS
設定に関する問題です。
useDNS
を有効にすると、SSH 接続時に IP アドレスの逆引きが行われます。
authorized_keys
に from="hostname"
のような記述をしておくと、接続元を特定のドメインを持つホストに限定したりできます。
しかし、何らかの理由で SSH 先の DNS サーバ設定がうまく行ってないと、DNS の逆引きでタイムアウトになるまで試行してしまうことがあり、 SSH 接続が遅くなったように感じられることがあります。
今回、ネットワーク構成図をよく見てみると、 Host2 の Nameserver が存在しない IP アドレスを指定しています。
ネットワーク構成図に書かれたもの以外のサーバやネットワーク機器は一切存在しないので、上記のような現象が発生しました。
このトラブル、どうやら昔からよくあるようで、「SSH 遅い」で検索してみると、結構上位に来ています。
問34
以下のような構成の Kubernetes リソースがある。
app1
、app2
はそれぞれ別々の Nginx Ingress があり、このそれぞれに外部の LB(ロードバランサ) が紐づけられている(ここでいう Nginx Ingress は、kubernetes/ingress-nginx を利用している)。
この外部LBは非常にコストがかかるため、LB を1つにまとめる方針になった。具体的には、app1
、app2
の Ingress を共通のものとして切り出し、common
という namespace にデプロイすることで、1つの LB だけですべてのサービスを公開できるようにしたい。
common.yml
、app1.yml
、app2.yml
の三種類のリソースを用意し、実際に検証を行ってみたところエラーが発生してしまった。
以下は common.yml
である。
kind: Namespace
apiVersion: v1
metadata:
name: common
labels:
name: common
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-ingress
namespace: common
spec:
ingressClassName: nginx
rules:
- host: app1.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
namespace: app1
name: app1-service
port:
number: 80
- host: app2.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
namespace: app2
name: app2-service
port:
number: 80
以下は app1.yml
である。
kind: Namespace
apiVersion: v1
metadata:
name: app1
labels:
name: app1
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: app1-deployment
namespace: app1
labels:
app: app1
spec:
replicas: 1
selector:
matchLabels:
app: app1
template:
metadata:
labels:
app: app1
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: app1-service
namespace: app1
labels:
app: app1
spec:
selector:
app: app1
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
以下は app2.yml
である。
kind: Namespace
apiVersion: v1
metadata:
name: app2
labels:
name: app2
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: app2-deployment
namespace: app2
labels:
app: app2
spec:
replicas: 1
selector:
matchLabels:
app: app2
template:
metadata:
labels:
app: app2
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: app2-service
namespace: app2
labels:
app: app2
spec:
selector:
app: app2
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
以下は実行したコマンドと発生したエラーである。
$ kubectl apply -f common.yml
Error from server (BadRequest): error when creating "common.yml": Ingress in version "v1" cannot be handled as a Ingress: strict decoding error: unknown field "spec.rules[0].http.paths[0].backend.service.namespace"
このエラーが発生している原因を記述せよ。
また、どのように YAML ファイルを変更すれば変更後の構成通り1つの LB で app1
、app2
を公開できるか、YAML の差分を記述せよ。
なお、以下の点に注意すること。
- 既存のリソースを変更する際は、YAML ファイル名と、どのリソース、キーをどのように変更したか記述する
- 例:
- 変更対象:
app1.yml
の Service (metadata.name: app1-service
)- 変更内容:
metadata.labels.app
をapp1
からapp1-hoge
に変更spec.ports[0].protocol
をTCP
からUDP
に変更
- 変更内容:
- 変更対象:
- 新規リソースを作成する際は、追記するファイル名と、新規リソースの定義を記述する
common
namespace のリソース以外は変更してはならないapp1
、app2
は別チームが開発しており、変更の権限がない- カスタムリソースは使用できない
- Ingress の annotation を変更(追加、削除、編集)してはならない
なお、Kubernetes クラスタの基本情報を以下に示す。
- Kubernetes Version: v1.33.1
- Cluster Domain:
cluster.local
正解
模範解答:
エラーの原因は、Ingress リソースの backend servic eには、namespace を指定できないことにある。
解決策としては、common
namespace にある Service を、ExternalName
Service に変更し、app1
と app2
それぞれにある Service の FQDN を指定する。
- 変更対象:
common.yml
のService
(metadata.name: app1-service
)- 変更内容:
spec.type
をExternalName
とするspec.externalName
を追加し、Value をapp1-service.app1.svc.cluster.local
とする
- 変更内容:
- 変更対象:
common.yml
のService
(metadata.name: app2-service
)- 変更内容:
spec.type
をExternalName
とするspec.externalName
を追加し、Value をapp2-service.app2.svc.cluster.local
とする
- 変更内容:
以下は想定する common.yml
である。
kind: Namespace
apiVersion: v1
metadata:
name: common
labels:
name: common
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-ingress
namespace: common
spec:
ingressClassName: nginx
rules:
- host: app1.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app1-service
port:
number: 80
- host: app2.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app2-service
port:
number: 80
---
apiVersion: v1
kind: Service
metadata:
name: app1-service
namespace: common
spec:
type: ExternalName
externalName: app1-service.app1.svc.cluster.local
---
apiVersion: v1
kind: Service
metadata:
name: app2-service
namespace: common
spec:
type: ExternalName
externalName: app2-service.app2.svc.cluster.local
解説
Ingress リソースを使って何とか LB を一つにできないかという問題です。
AWS で EKS を使っていたりすると、1つの Ingress に対して 1つの ALB が立ち上がっており、思ったより料金がかかっていた...というあるある(?)です。開発環境だと環境が増えまくるので、気を付けなければいけないポイントだと思います。
まず、エラーが発生してしまっていた理由ですが、エラーメッセージの通り、Ingress (Kubernetes v1.33) リソースには、spec.rules[0].http.paths[0].backend.service.namespace
のように、service
に対して namespace
を指定することはできません。
つまり、Ingress リソース単体では、別 namespace のリソースを参照できないのです。
様々な方法で回避ができますが、今回は ExternalName
Service を想定して作問してみました。
ExternalName
Service は、Service を特定ドメインにマッピングしてくれます。
例えば、example.com
というドメインを example
という名前の Service にマッピングできます。内部的には、example
Service の FQDN を、example.com
の CNAME として登録することで実現しています。
さて、この ExternalName を app1
、app2
namespace にある Service を参照するために使ってみましょう。
Service リソースには、 FQDN が割り当てられており、これは他の namespace からも名前解決ができます。
そこで、common
namespace に、app1
の app1-service
、 app2
の app2-service
を参照する ExternalName
Service を使えば、他の namespace の Service も参照できるようになるというわけです。
採点基準
今回は、採点基準を作るのにかなり苦戦しました。というのも、解答のバリエーションが様々だったからです。
この問題は12点問題で、大まかな方針としては、
- 原因を正しく指摘できていれば6点
- YAMLファイルの差分を正しく記述できていれば6点
としました。
また、ExternalName
Service を使わない解答もすべてローカル環境で動作確認をし、方針として問題が無ければ正答としています(満点でない場合は、タイポ等の細かいミスで減点している可能性が高いです)
模範解答以外の方針としては、以下のようなものがありました
common
namespace にnginx deployment, Service
を置いて、app1,2
の Service に対して proxy するapp1-service
の IP を参照するEntrypoints
リソースを作成し、common
リソースにそれを参照する Service を置く
その他、細かい基準に関しては以下に書いておきます。
- 原因を正しく指摘できている(namespaceを指定してしまっている): 6点
- 原因を書き忘れているが、問題を解決できている場合は3点
- YAMLファイルの差分を正しく記述できている: 6点
- 正しく記述できているの基準
- type:ExternalService を指定したサービスを作れている: 6点
- YAMLや差分の記述等からExternalServiceを作ろうとしていることが分かれば2点
- ExternalService のフォーマットに従っている
- type: ExternalService で1点
- externalName で1点
- パラメータミス(綴りミス等ではなく不足など)の場合は2点マイナス
- その他
- 単純なtypoなら1点マイナス
- インデント誤りはtypoとしない
- 問題文に指定されていた差分を記述していない場合(変更後だけを載せている場合)などは2点減点
- namespace の指定を削除しただけでは0点(問題文に、ゴールがLB1台でサービスを公開できていることと指定されているので)
- port などを指定している場合は特に減点なし
- ExternalName タイプのサービスは、DNS の CNAME として機能するため、ポートを指定しても動作に何も影響がない。(80番ポート以外を指定してもOK)
- その他の解法は、動作確認の上、下記基準で採点しています
- 問題の構成をきちんと再現できている: 6点
- kubectl applyコマンドでデプロイができない(YAML形式ミス、バリデーションエラー等)場合は2点マイナス
- パラメータミス(サービス名の指定ミス)などが1,2カ所程度あれば2点マイナス
- 再現できない場合も、大まかな方針が合っていれば2点
問35
メール認証技術について、間違っているものを全て選べ。
選択肢(複数選択)
- SPF と DKIM の両方が成功すれば、DMARC 認証は必ず成功する
- DMRAC 認証が失敗し、
p=reject
の場合は、メールは常に届かない - DKIM の署名は、DKIM-Signature ヘッダにある d タグにあるドメインに対して行われる
- SPF は、メールヘッダの From に記載されたアドレスのドメインを検証する
正解
1, 2, 4
解説
メールの認証技術に関する問題です。
正しい記述の選択肢
-
- 「DKIM の署名は、DKIM-Signature ヘッダにある d タグにあるドメインに対して行われる」
- 記載の通りです。
間違っている記述の選択肢
- 1.「SPF と DKIM の両方が成功すれば、DMARC 認証は必ず成功する」
- DMARC が成功 = pass するには、SPF と DKIM 以外にも、それぞれの「アライメント」が関係します。
- DMARCが成功するには、「SPF が成功 and SPFアライメント(ヘッダ From とエンベロープ From が一致)が成功」 or 「DKIM が成功 and DKIM アライメント(dタグで指定されたドメインとヘッダ From が一致)」が条件となります。なので、SPF とDKIM が両方成功していても、それぞれのアライメントが両方とも失敗している場合はDMARC 認証は失敗します。
- 2.「DMRAC 認証が失敗し、
p=reject
の場合は、メールは常に届かない」- DMARC のポリシーはあくまでも推奨であり、強制ではありません。
- DMARC 認証が失敗し、ポリシーで
reject
を指定されていたとしても、メール受信者のlocal_policy
などで DMARC ポリシーが上書きされている場合は配信することがあります。
- 4.「SPF は、メールヘッダの From に記載されたアドレスのドメインを検証する」
- 間違いです。SPF では、メールヘッダではなくエンベロープ From に記載されたアドレスのドメインを検証します