Skip to content
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

NewSDK configurable 'host' #3634

Closed
DazEdword opened this issue Feb 5, 2024 · 4 comments · Fixed by #3676
Closed

NewSDK configurable 'host' #3634

DazEdword opened this issue Feb 5, 2024 · 4 comments · Fixed by #3676
Assignees
Labels
kind/feature New features for Agones

Comments

@DazEdword
Copy link

DazEdword commented Feb 5, 2024

Is your feature request related to a problem? Please describe.
I'm using Docker to run containerized GameServers/SDK for local development. I'm also using GitLab's CICD with DIND to run the same automated tests. As part of the tests, we start and agones-sdk container in host network mode, with tests later creating an SDK client that would be used to test functionality. This sort works well locally. However, the SDK to connect locally (localhost:9357) won't work on DIND since (docker:9357) is required. I'm using Golang's SDK.

Describe the solution you'd like
I would love to be able to instantiate the SDK with NewSDK, and modify the hardcoded localhost. The actual implementation I don't feel strongly about, but for instance options could be:

  1. Accept an opts struct with a host param.
  2. Read AGONES_SDK_GRPC_HOST env var and override the host if present. Apparently suggested before for a different SDK: Adding AGONES_SDK_GRPC_HOST to NewSDK #1183

Describe alternatives you've considered
I have researches GitLab's DIND capabilities, but my understanding is that the way docker-in-docker works, there's no way around network configuration. The host needs to be docker.

Additional context
None.

@DazEdword DazEdword added the kind/feature New features for Agones label Feb 5, 2024
@roberthbailey
Copy link
Member

I don't have a particularly strong objection to making the host configurable, but it feels like even with docker-in-docker you should be able to configure the networking so that the two containers share the same network namespace.

I found this medium article that explains How Can Two Containers Communicate Via localhost on Docker? and I've also found some references to using network_mode = "host" in /etc/gitlab-runner/config.toml to allow connections over localhost. It seems like it should be possible to configure the network for this to work (as was found with docker compose in #1183).

@markmandel
Copy link
Member

To second @roberthbailey - while I'm not familiar with GitLab's CI, I've definitely done --network=host in DIND.

For example, this Makefile target test-quilkin:
https://github.com/googleforgames/quilkin/blob/81db684cadcd7f28c32306cd4d72116b50ca6e83/build/Makefile#L90-L92

Is run in Google Cloud Build (that is also DIND):
https://github.com/googleforgames/quilkin/blob/81db684cadcd7f28c32306cd4d72116b50ca6e83/cloudbuild.yaml#L26-L29

As a thought, if you can share how you are running your tests on GitLab CI, we can possibly point out a path through. My gut tells me you may need to call docker run --network=host ... directly (rather than indirectly like how Cloud Build does it), but let's see what you have and we can take it from there.

@DazEdword
Copy link
Author

Hey folks, thanks for the responses! After doing a bit more reading I think this is not a problem around DIND but rather a particularity of GitLab. That said, I think something along these lines could help in my case:

https://docs.gitlab.com/ee/ci/services/#using-services-with-docker-run-docker-in-docker-side-by-side

I'll give it a go later today and return with more details.

@DazEdword
Copy link
Author

Hi again, I've had a look and although I could not go through til the end I'm relatively confident it can work without the custom host, but it's going to affect the way I run the tests anyway. Which btw @markmandel , I've realised I haven't shared yet despite your request, it's been a busy day 😶‍🌫️ .

Basically the way we're running tests is through a dedicated check job in a validation stage. That job will simply translate into running go test ./....

As part of my tests, I have a testcontainers fixture that will create a short-lived containerised game server before the test, and will tear it down after the test. My GitLab config has already some fields for GitLab DIND to play nicely with testcontainers:

  services:
    - name: docker:24.0.7-dind
    # explicitly disable tls to avoid docker startup interruption
      command: ["--tls=false"]
  variables:
    # instruct Testcontainers to use the daemon of DinD, use port 2375 for non-tls connections.
    DOCKER_HOST: "tcp://docker:2375"
    # istruct Docker not to start over TLS.
    DOCKER_TLS_CERTDIR: ""
    # improve performance with overlayfs.
    DOCKER_DRIVER: overlay2
    # Tell Testcontainers that DinD hostname is docker and not localhost
    TC_HOST: docker

My actual testcontainers fixture looks more or less like this:

Setup:

func AgonesSdkContainerFixture(t *testing.T) (context.Context, testcontainers.Container) {
	ctx := context.Background()

	abs, err := filepath.Abs("./")
	require.NoError(t, err)

	gameserverYamlPath := path.Join(abs, "gameserver.yaml")

	req := testcontainers.ContainerRequest{
		Image:        "us-docker.pkg.dev/agones-images/release/agones-sdk:1.37.0",
		ExposedPorts: []string{"9357/tcp", "9358/tcp"},
		WaitingFor:   wait.ForLog("Starting SDKServer grpc-gateway..."),
		HostConfigModifier: func(hc *container.HostConfig) {
			hc.NetworkMode = "host"
			hc.Binds = []string{gameserverYamlPath + ":" + "/tmp/gameserver.yaml"}
		},
		Cmd: []string{"--local", "--feature-gates", "CountsAndLists=true", "-f", "/tmp/gameserver.yaml"},
	}

	agonesC, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
		ContainerRequest: req,
		Started:          true,
	})
	if err != nil {
		t.Fatal(err)
	}

	return ctx, agonesC
}

Teardown:


func AgonesSdkContainerCleanup(ctx context.Context, t *testing.T, agonesC testcontainers.Container) {
	if err := agonesC.Terminate(ctx); err != nil {
		t.Fatalf("failed to terminate container: %s", err.Error())
	}
}

As I mentioned above, if I go down the GitLab service route, I will then have a single GameServer running alongside my application tests, instead of the ephemeral gameservers that I was aiming to have (I know this is not efficient, but hey test code, I prefer the reliability over the efficiency).

I wouldn't suggest the configurable host if it was production code, but since it's the simple server I think I'd like to maintain my request. Otherwise, if you have suggestions to harmonize GitLab's DIND + network host + ephemeral testcontainers I'll be more than happy to test it out!

Again thanks for your support 👏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/feature New features for Agones
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants