abstractdog commented on code in PR #473:
URL: https://github.com/apache/tez/pull/473#discussion_r3490405085
##########
tez-api/src/main/java/org/apache/tez/dag/api/TezConfiguration.java:
##########
@@ -2420,4 +2423,12 @@ static Set<String> getPropertySet() {
@ConfigurationScope(Scope.AM)
@ConfigurationProperty
public static final String TEZ_AM_STANDALONE_CONFS = TEZ_AM_PREFIX +
"standalone.confs";
+
+ /**
+ * String value. Namespace in ZooKeeper registry for the TezChild
+ */
+ @ConfigurationScope(Scope.VERTEX)
+ @ConfigurationProperty
+ public static final String TEZ_TASK_REGISTRY_NAMESPACE = TEZ_TASK_PREFIX +
"registry.namespace";
+ public static final String TEZ_TASK_REGISTRY_NAMESPACE_DEFAULT =
"/tez_am/workers";
Review Comment:
`/tez_am/workers` looks a bit strange, a component is an `am` or a `worker`
as the zookeeper registry hasn't been released yet, we're free to modify the
default values, what about:
for AM: `/tez-am`
for tasks: `/tez-worker`
so if we consider the root `/tez-external-sessions` prefix, they'll end up
in:
```
/tez-external-sessions/tez-am
/tez-external-sessions/tez-worker
```
this way we can stick to hyphen for the static prefixes, and underscore for
the dynamic container ids
additional changes needed: moving this below to `TezConstants` class and
making it public:
```
ZK_NAMESPACE_PREFIX = "/tez-external-sessions";
```
##########
tez-dag/src/main/java/org/apache/tez/dag/app/launcher/NoOpContainerLauncher.java:
##########
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tez.dag.app.launcher;
+
+import org.apache.tez.serviceplugins.api.ContainerLaunchRequest;
+import org.apache.tez.serviceplugins.api.ContainerLauncher;
+import org.apache.tez.serviceplugins.api.ContainerLauncherContext;
+import org.apache.tez.serviceplugins.api.ContainerStopRequest;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A No-Op Container Launcher where TezChild processes are started externally
(e.g., via Docker
+ * Compose or Kubernetes).
+ */
+public class NoOpContainerLauncher extends ContainerLauncher {
+
+ private static final Logger LOG =
LoggerFactory.getLogger(NoOpContainerLauncher.class);
+
+ public NoOpContainerLauncher(ContainerLauncherContext
containerLauncherContext) {
+ super(containerLauncherContext);
+ }
+
+ /** This method is no-op it's just informing AM to change container state */
+ @Override
+ public void launchContainer(ContainerLaunchRequest launchRequest) {
+ LOG.info("Container is externally managed: {}",
launchRequest.getContainerId());
+
+ // Immediately tell AM that the container is "launched"
+ getContext().containerLaunched(launchRequest.getContainerId());
+ }
+
+ /** This method is no-op it's just informing AM to change container state */
+ @Override
+ public void stopContainer(ContainerStopRequest stopRequest) {
+ LOG.info("Lifecycle is externally managed for container: {}",
stopRequest.getContainerId());
Review Comment:
message should contain the actual fact also that this is a "stop" call
##########
tez-dag/src/main/java/org/apache/tez/dag/app/launcher/NoOpContainerLauncher.java:
##########
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tez.dag.app.launcher;
+
+import org.apache.tez.serviceplugins.api.ContainerLaunchRequest;
+import org.apache.tez.serviceplugins.api.ContainerLauncher;
+import org.apache.tez.serviceplugins.api.ContainerLauncherContext;
+import org.apache.tez.serviceplugins.api.ContainerStopRequest;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A No-Op Container Launcher where TezChild processes are started externally
(e.g., via Docker
+ * Compose or Kubernetes).
+ */
+public class NoOpContainerLauncher extends ContainerLauncher {
+
+ private static final Logger LOG =
LoggerFactory.getLogger(NoOpContainerLauncher.class);
+
+ public NoOpContainerLauncher(ContainerLauncherContext
containerLauncherContext) {
+ super(containerLauncherContext);
+ }
+
+ /** This method is no-op it's just informing AM to change container state */
+ @Override
+ public void launchContainer(ContainerLaunchRequest launchRequest) {
+ LOG.info("Container is externally managed: {}",
launchRequest.getContainerId());
Review Comment:
message should contain the actual fact also that this is a "launch" call
##########
tez-runtime-library/src/main/java/org/apache/tez/runtime/library/common/TezRuntimeUtils.java:
##########
@@ -271,6 +271,9 @@ public static BaseHttpConnection getHttpConnection(boolean
asyncHttp, URL url,
public static int deserializeShuffleProviderMetaData(ByteBuffer meta)
throws IOException {
+ if (meta == null) {
+ return 0;
+ }
Review Comment:
hm, need to know what is this a workaround for
##########
tez-dist/src/docker/entrypoint.sh:
##########
@@ -0,0 +1,34 @@
+#!/usr/bin/env bash
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+set -xeou pipefail
+
+: "${TEZ_COMPONENT:="AM"}"
+
+echo "--> Starting Tez Component: $TEZ_COMPONENT"
+
+if [[ "$TEZ_COMPONENT" == "AM" ]]; then
+ echo "--> Routing to Tez AM Entrypoint"
+ exec /am-entrypoint.sh "$@"
+elif [[ "$TEZ_COMPONENT" == "CHILD" ]]; then
+ echo "--> Routing to Tez Child Entrypoint"
+ exec /child-entrypoint.sh "$@"
Review Comment:
"child" might imply they are actually created out of a "parent" task, which
is not the case, as they are just simple, independent workers
currently, we usually refer to them as "task" containers
just thinking aloud: so before renaming every occurrence of "child" to
"task", we can also consider using "worker" consistently, especially because
the `TezChild` behavior is going to be altered
##########
tez-dist/src/docker/docker-compose.yml:
##########
@@ -142,3 +176,7 @@ volumes:
name: zookeeper_datalog
zookeeper_logs:
name: zookeeper_logs
+ tez_shared_data:
+ name: tez_shared_data
+ tez_shared_tmp:
+ name: tez_shared_tmp
Review Comment:
when the implementation is ready, please don't forget to comment here what's
supposed to be in tmp, what's in shared and what's local
also especially interested what's "tez_shared_tmp": it looks strange for the
first sight that containers share some temporary data: I believe, the naming
should be more specific to the use case than "tmp"
##########
tez-dist/src/docker/README.md:
##########
@@ -0,0 +1,196 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+# Apache Tez Docker
+
+This directory contains a unified Docker implementation for running TezAM
+and TezChild process from a single container image. Based on
+`TEZ_COMPONENT` environment variable the entrypoint is dynamically selected
+
+1. Building the docker image:
+
+ ```bash
+ mvn clean install -DskipTests -Pdocker
+ ```
+
+ Alternatively, you can build it explicitly via the provided script:
+
+ ```bash
+ ./tez-dist/src/docker/build.sh -tez <version> -repo apache
+ ```
+
+2. Local Zookeeper Setup (Standalone):
+
+ If you are running the AM container use the official Docker
+ image (Refer to docker-compose.yml):
+
+ ```bash
+ docker pull zookeeper:3.8.4
+
+ docker run -d \
+ --name zookeeper-server \
+ -p 2181:2181 \
+ -p 8080:8080 \
+ -e ZOO_MY_ID=1 \
+ zookeeper:3.8.4
+ ```
+
+3. Running the Tez containers explicitly:
+
+ **Running the Tez AM:**
+
+ ```bash
+ export TEZ_VERSION=1.0.0-SNAPSHOT
+
+ docker run --rm \
+ -p 10001:10001 \
+ --env-file tez-dist/src/docker/am.env \
+ --name tez-am \
+ --hostname localhost \
+ apache/tez:$TEZ_VERSION
+ ```
+
+ * `TEZ_VERSION` corresponds to the Maven `${project.version}`.
+ Set this environment variable in your shell before running the commands.
+
+ * Expose ports using the `-p` flag based on the
+ `tez.am.client.am.port-range` property in `tez-site.xml`.
+
+ * The `--hostname` flag configures the container's hostname, allowing
+ services on the host (e.g., macOS) to connect to it.
+
+ * Ensure the `--env-file` flag is included, or at a minimum, pass
+ `-e TEZ_FRAMEWORK_MODE=STANDALONE_ZOOKEEPER` and `-e TEZ_COMPONENT=AM`
+ to the `docker run` command.
+
+ **Running the Tez Child:**
+
+ The child container requires specific arguments (`<am-host> <am-port>
+ <container-id> <token-id> <attempt-number>`) to connect back to the
+ Application Master.
+
+ Assuming your AM is running on `localhost` port `10001`, and the AM
+ assigned the container ID `container_1703023223000_0001_01_000001`:
+
+ ```bash
+ docker run --rm \
+ --network host \
+ --env-file tez-dist/src/docker/child.env \
+ --name tez-child \
+ --hostname localhost \
+ apache/tez:1.0.0-SNAPSHOT \
+ localhost 10001 container_1703023223000_0001_01_000001 dummy_token_abc 1
+ ```
+
+4. Debugging the Tez containers:
+ Uncomment the `JAVA_TOOL_OPTIONS` in `am.env` (or `child.env` for
+ port 5006) and expose the debug port using `-p` flag:
+
+ ```bash
+ docker run --rm \
+ -p 10001:10001 -p 5005:5005 \
+ --env-file tez-dist/src/docker/am.env \
+ --name tez-am \
+ --hostname localhost \
+ apache/tez:$TEZ_VERSION
+ ```
Review Comment:
this section could also be removed: the docker-compose file should make this
part clear
##########
tez-dist/src/docker/README.md:
##########
@@ -0,0 +1,196 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+# Apache Tez Docker
+
+This directory contains a unified Docker implementation for running TezAM
+and TezChild process from a single container image. Based on
+`TEZ_COMPONENT` environment variable the entrypoint is dynamically selected
+
+1. Building the docker image:
+
+ ```bash
+ mvn clean install -DskipTests -Pdocker
+ ```
+
+ Alternatively, you can build it explicitly via the provided script:
+
+ ```bash
+ ./tez-dist/src/docker/build.sh -tez <version> -repo apache
+ ```
+
+2. Local Zookeeper Setup (Standalone):
+
+ If you are running the AM container use the official Docker
+ image (Refer to docker-compose.yml):
+
+ ```bash
+ docker pull zookeeper:3.8.4
+
+ docker run -d \
+ --name zookeeper-server \
+ -p 2181:2181 \
+ -p 8080:8080 \
+ -e ZOO_MY_ID=1 \
+ zookeeper:3.8.4
+ ```
+
+3. Running the Tez containers explicitly:
+
+ **Running the Tez AM:**
+
+ ```bash
+ export TEZ_VERSION=1.0.0-SNAPSHOT
+
+ docker run --rm \
+ -p 10001:10001 \
+ --env-file tez-dist/src/docker/am.env \
+ --name tez-am \
+ --hostname localhost \
+ apache/tez:$TEZ_VERSION
+ ```
+
+ * `TEZ_VERSION` corresponds to the Maven `${project.version}`.
+ Set this environment variable in your shell before running the commands.
+
+ * Expose ports using the `-p` flag based on the
+ `tez.am.client.am.port-range` property in `tez-site.xml`.
+
+ * The `--hostname` flag configures the container's hostname, allowing
+ services on the host (e.g., macOS) to connect to it.
+
+ * Ensure the `--env-file` flag is included, or at a minimum, pass
+ `-e TEZ_FRAMEWORK_MODE=STANDALONE_ZOOKEEPER` and `-e TEZ_COMPONENT=AM`
+ to the `docker run` command.
+
+ **Running the Tez Child:**
+
+ The child container requires specific arguments (`<am-host> <am-port>
+ <container-id> <token-id> <attempt-number>`) to connect back to the
+ Application Master.
+
+ Assuming your AM is running on `localhost` port `10001`, and the AM
+ assigned the container ID `container_1703023223000_0001_01_000001`:
+
+ ```bash
+ docker run --rm \
+ --network host \
+ --env-file tez-dist/src/docker/child.env \
+ --name tez-child \
+ --hostname localhost \
+ apache/tez:1.0.0-SNAPSHOT \
+ localhost 10001 container_1703023223000_0001_01_000001 dummy_token_abc 1
+ ```
+
+4. Debugging the Tez containers:
+ Uncomment the `JAVA_TOOL_OPTIONS` in `am.env` (or `child.env` for
+ port 5006) and expose the debug port using `-p` flag:
+
+ ```bash
+ docker run --rm \
+ -p 10001:10001 -p 5005:5005 \
+ --env-file tez-dist/src/docker/am.env \
+ --name tez-am \
+ --hostname localhost \
+ apache/tez:$TEZ_VERSION
+ ```
+
+5. To override the tez-site.xml in docker image use:
+
+ * Set the `TEZ_CUSTOM_CONF_DIR` environment variable in `am.env` /
+ `child.env` or via the `docker run` command (e.g.,
+ `/opt/tez/custom-conf`).
+
+ ```bash
+ export TEZ_SITE_PATH=$(pwd)/tez-dist/src/docker/conf/tez-site.xml
+
+ docker run --rm \
+ -p 10001:10001 \
+ --env-file tez-dist/src/docker/am.env \
+ -v "$TEZ_SITE_PATH:/opt/tez/custom-conf/tez-site.xml" \
+ --name tez-am \
+ --hostname localhost \
+ apache/tez:$TEZ_VERSION
+ ```
Review Comment:
this section can be replaced with a some tips pointing to a starter script:
```
export TEZ_SITE_PATH=$(pwd)/tez-dist/src/docker/conf/tez-site.xml #this is a
path on the host machine that the developer can mess with :D
./start-tez.sh
```
this will make the testing with custom configuration extremely easy
##########
tez-dist/src/docker/README.md:
##########
@@ -0,0 +1,196 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+# Apache Tez Docker
+
+This directory contains a unified Docker implementation for running TezAM
+and TezChild process from a single container image. Based on
+`TEZ_COMPONENT` environment variable the entrypoint is dynamically selected
+
+1. Building the docker image:
+
+ ```bash
+ mvn clean install -DskipTests -Pdocker
+ ```
+
+ Alternatively, you can build it explicitly via the provided script:
+
+ ```bash
+ ./tez-dist/src/docker/build.sh -tez <version> -repo apache
+ ```
+
+2. Local Zookeeper Setup (Standalone):
+
+ If you are running the AM container use the official Docker
+ image (Refer to docker-compose.yml):
+
+ ```bash
+ docker pull zookeeper:3.8.4
+
+ docker run -d \
+ --name zookeeper-server \
+ -p 2181:2181 \
+ -p 8080:8080 \
+ -e ZOO_MY_ID=1 \
+ zookeeper:3.8.4
+ ```
+
+3. Running the Tez containers explicitly:
+
+ **Running the Tez AM:**
+
+ ```bash
+ export TEZ_VERSION=1.0.0-SNAPSHOT
+
+ docker run --rm \
+ -p 10001:10001 \
+ --env-file tez-dist/src/docker/am.env \
+ --name tez-am \
+ --hostname localhost \
+ apache/tez:$TEZ_VERSION
+ ```
+
+ * `TEZ_VERSION` corresponds to the Maven `${project.version}`.
+ Set this environment variable in your shell before running the commands.
+
+ * Expose ports using the `-p` flag based on the
+ `tez.am.client.am.port-range` property in `tez-site.xml`.
+
+ * The `--hostname` flag configures the container's hostname, allowing
+ services on the host (e.g., macOS) to connect to it.
+
+ * Ensure the `--env-file` flag is included, or at a minimum, pass
+ `-e TEZ_FRAMEWORK_MODE=STANDALONE_ZOOKEEPER` and `-e TEZ_COMPONENT=AM`
+ to the `docker run` command.
+
+ **Running the Tez Child:**
+
+ The child container requires specific arguments (`<am-host> <am-port>
+ <container-id> <token-id> <attempt-number>`) to connect back to the
+ Application Master.
+
+ Assuming your AM is running on `localhost` port `10001`, and the AM
+ assigned the container ID `container_1703023223000_0001_01_000001`:
+
+ ```bash
+ docker run --rm \
+ --network host \
+ --env-file tez-dist/src/docker/child.env \
+ --name tez-child \
+ --hostname localhost \
+ apache/tez:1.0.0-SNAPSHOT \
+ localhost 10001 container_1703023223000_0001_01_000001 dummy_token_abc 1
+ ```
+
+4. Debugging the Tez containers:
+ Uncomment the `JAVA_TOOL_OPTIONS` in `am.env` (or `child.env` for
+ port 5006) and expose the debug port using `-p` flag:
+
+ ```bash
+ docker run --rm \
+ -p 10001:10001 -p 5005:5005 \
+ --env-file tez-dist/src/docker/am.env \
+ --name tez-am \
+ --hostname localhost \
+ apache/tez:$TEZ_VERSION
+ ```
+
+5. To override the tez-site.xml in docker image use:
+
+ * Set the `TEZ_CUSTOM_CONF_DIR` environment variable in `am.env` /
+ `child.env` or via the `docker run` command (e.g.,
+ `/opt/tez/custom-conf`).
+
+ ```bash
+ export TEZ_SITE_PATH=$(pwd)/tez-dist/src/docker/conf/tez-site.xml
+
+ docker run --rm \
+ -p 10001:10001 \
+ --env-file tez-dist/src/docker/am.env \
+ -v "$TEZ_SITE_PATH:/opt/tez/custom-conf/tez-site.xml" \
+ --name tez-am \
+ --hostname localhost \
+ apache/tez:$TEZ_VERSION
+ ```
+
+6. To add plugin jars in docker image use:
+
+ * The plugin directory path inside the Docker container is fixed at
+ `/opt/tez/plugins`.
+
+ ```bash
+ docker run --rm \
+ -p 10001:10001 \
+ --env-file tez-dist/src/docker/am.env \
+ -v "/path/to/your/local/plugins:/opt/tez/plugins" \
+ --name tez-am \
+ --hostname localhost \
+ apache/tez:$TEZ_VERSION
+ ```
+
+7. Using Docker Compose (Local Testing Cluster):
+
+ The provided `docker-compose.yml` offers a complete, minimal Hadoop
+ ecosystem to test Tez in a distributed manner locally without setting
+ up a real cluster.
+
+ **Services Included:**
+
+ * **namenode & datanode:** A minimal Apache Hadoop HDFS cluster
Review Comment:
even if I was in favor of using hadoop components earlier, know I believe we
should try to move away from `namenode`and `datanode`, and simply share folders
for the containers
I know this might need a re-design at some point, but it's worth the effort
e.g. hive's docker compose now runs a full cluster without any hadoop:
https://github.com/apache/hive/blob/9e38b8a3c58720899f413fe2531fed4138fb0a7f/packaging/src/docker/docker-compose.yml#L109-L110
##########
tez-dist/src/docker/README.md:
##########
@@ -0,0 +1,196 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+# Apache Tez Docker
+
+This directory contains a unified Docker implementation for running TezAM
+and TezChild process from a single container image. Based on
+`TEZ_COMPONENT` environment variable the entrypoint is dynamically selected
+
+1. Building the docker image:
+
+ ```bash
+ mvn clean install -DskipTests -Pdocker
+ ```
+
+ Alternatively, you can build it explicitly via the provided script:
+
+ ```bash
+ ./tez-dist/src/docker/build.sh -tez <version> -repo apache
+ ```
+
+2. Local Zookeeper Setup (Standalone):
+
+ If you are running the AM container use the official Docker
+ image (Refer to docker-compose.yml):
+
+ ```bash
+ docker pull zookeeper:3.8.4
+
+ docker run -d \
+ --name zookeeper-server \
+ -p 2181:2181 \
+ -p 8080:8080 \
+ -e ZOO_MY_ID=1 \
+ zookeeper:3.8.4
+ ```
+
+3. Running the Tez containers explicitly:
+
+ **Running the Tez AM:**
+
+ ```bash
+ export TEZ_VERSION=1.0.0-SNAPSHOT
+
+ docker run --rm \
+ -p 10001:10001 \
+ --env-file tez-dist/src/docker/am.env \
+ --name tez-am \
+ --hostname localhost \
+ apache/tez:$TEZ_VERSION
+ ```
+
+ * `TEZ_VERSION` corresponds to the Maven `${project.version}`.
+ Set this environment variable in your shell before running the commands.
+
+ * Expose ports using the `-p` flag based on the
+ `tez.am.client.am.port-range` property in `tez-site.xml`.
+
+ * The `--hostname` flag configures the container's hostname, allowing
+ services on the host (e.g., macOS) to connect to it.
+
+ * Ensure the `--env-file` flag is included, or at a minimum, pass
+ `-e TEZ_FRAMEWORK_MODE=STANDALONE_ZOOKEEPER` and `-e TEZ_COMPONENT=AM`
+ to the `docker run` command.
+
+ **Running the Tez Child:**
+
+ The child container requires specific arguments (`<am-host> <am-port>
+ <container-id> <token-id> <attempt-number>`) to connect back to the
+ Application Master.
+
+ Assuming your AM is running on `localhost` port `10001`, and the AM
+ assigned the container ID `container_1703023223000_0001_01_000001`:
+
+ ```bash
+ docker run --rm \
+ --network host \
+ --env-file tez-dist/src/docker/child.env \
+ --name tez-child \
+ --hostname localhost \
+ apache/tez:1.0.0-SNAPSHOT \
+ localhost 10001 container_1703023223000_0001_01_000001 dummy_token_abc 1
+ ```
+
+4. Debugging the Tez containers:
+ Uncomment the `JAVA_TOOL_OPTIONS` in `am.env` (or `child.env` for
+ port 5006) and expose the debug port using `-p` flag:
+
+ ```bash
+ docker run --rm \
+ -p 10001:10001 -p 5005:5005 \
+ --env-file tez-dist/src/docker/am.env \
+ --name tez-am \
+ --hostname localhost \
+ apache/tez:$TEZ_VERSION
+ ```
+
+5. To override the tez-site.xml in docker image use:
+
+ * Set the `TEZ_CUSTOM_CONF_DIR` environment variable in `am.env` /
+ `child.env` or via the `docker run` command (e.g.,
+ `/opt/tez/custom-conf`).
+
+ ```bash
+ export TEZ_SITE_PATH=$(pwd)/tez-dist/src/docker/conf/tez-site.xml
+
+ docker run --rm \
+ -p 10001:10001 \
+ --env-file tez-dist/src/docker/am.env \
+ -v "$TEZ_SITE_PATH:/opt/tez/custom-conf/tez-site.xml" \
+ --name tez-am \
+ --hostname localhost \
+ apache/tez:$TEZ_VERSION
+ ```
+
+6. To add plugin jars in docker image use:
+
+ * The plugin directory path inside the Docker container is fixed at
+ `/opt/tez/plugins`.
+
+ ```bash
+ docker run --rm \
+ -p 10001:10001 \
+ --env-file tez-dist/src/docker/am.env \
+ -v "/path/to/your/local/plugins:/opt/tez/plugins" \
+ --name tez-am \
+ --hostname localhost \
+ apache/tez:$TEZ_VERSION
+ ```
+
+7. Using Docker Compose (Local Testing Cluster):
+
+ The provided `docker-compose.yml` offers a complete, minimal Hadoop
+ ecosystem to test Tez in a distributed manner locally without setting
+ up a real cluster.
+
+ **Services Included:**
+
+ * **namenode & datanode:** A minimal Apache Hadoop HDFS cluster
+ (lean image)
+
+ * **zookeeper:** Required by the Tez AM for standalone session
+ discovery
+
+ * **tez-am:** It automatically waits for Zookeeper and HDFS to
+ be healthy before starting up.
+
+ * **tez-child:** TBD
Review Comment:
this list of containers is not a must-have here, docker-compose must be
clean and self-descriptive
##########
tez-runtime-internals/src/main/java/org/apache/tez/runtime/task/TezChild.java:
##########
@@ -517,45 +531,112 @@ public static TezChild newTezChild(Configuration conf,
String host, int port, St
hadoopShim);
}
- public static void main(String[] args) throws IOException,
InterruptedException, TezException {
+ public static void main(String[] args) throws Exception {
TezClassLoader.setupTezClassLoader();
final Configuration defaultConf = new Configuration();
+ String frameworkMode = System.getenv(TezConstants.TEZ_FRAMEWORK_MODE);
+
+ String host, appId, tokenIdentifier, containerIdentifier;
+ int port, attemptNumber;
+ Credentials credentials = new Credentials();
+
+ if (STANDALONE_ZOOKEEPER.name().equalsIgnoreCase(frameworkMode)) {
+ DAGProtos.ConfigurationProto confProtoBefore =
TezUtilsInternal.loadConfProtoFromText();
+ TezUtilsInternal.addUserSpecifiedTezConfiguration(
+ defaultConf, confProtoBefore.getConfKeyValuesList());
+
+ ZkAMRegistryClient registry = ZkAMRegistryClient.getClient(defaultConf);
+ registry.start();
+
+ // TODO: Expose retry counter and sleep time as config — in ZKconfig or
TezConfig?
+ while (!registry.isInitialized()) {
+ TimeUnit.SECONDS.sleep(5);
+ }
+
+ List<AMRecord> records = registry.getAllRecords();
+ if (records.isEmpty()) {
+ throw new RuntimeException("No AM found in ZooKeeper registry");
+ }
+ // TODO: Should we always get the first or there should be some
sophisticated logic?
+ AMRecord amRecord = records.getFirst();
+
+ host = amRecord.getHostName();
+ String portRange =
+ defaultConf.getTrimmed(TezConfiguration.TEZ_AM_TASK_AM_PORT_RANGE,
"12000-12000");
+ port = Integer.parseInt(portRange.split("[-,]")[0]);
+
+ appId = amRecord.getApplicationId().toString();
Review Comment:
this part is crucial from design perspective: the current implementation
here assumes the following behavior:
1. AM starts first
2. AM registers its application id in zookeeper
3. Task container starts
4. Task starts a registry client, and picks the first discoverable AM
let's assume a kubernetes cluster later, multiple tenants, so multiple
applications, and therefore concurrent DAGs
I'm afraid that with the current implementation, we simply lose our control
to start an application with the desired resources (so the desired amount of
task containers), because task containers just start and pick the first AM from
the zookeeper registry
instead, we should have a clear connection between them, which might be the
application_id/container_id (which is similar to yarn world tez container
mode), and when the task container starts, it already knows which application
it belongs to: I guess here this logical connection is around because you
already pass a container id for the TezChild
##########
tez-runtime-internals/src/main/java/org/apache/tez/runtime/task/TezChild.java:
##########
@@ -517,45 +531,112 @@ public static TezChild newTezChild(Configuration conf,
String host, int port, St
hadoopShim);
}
- public static void main(String[] args) throws IOException,
InterruptedException, TezException {
+ public static void main(String[] args) throws Exception {
TezClassLoader.setupTezClassLoader();
final Configuration defaultConf = new Configuration();
+ String frameworkMode = System.getenv(TezConstants.TEZ_FRAMEWORK_MODE);
+
+ String host, appId, tokenIdentifier, containerIdentifier;
+ int port, attemptNumber;
+ Credentials credentials = new Credentials();
+
+ if (STANDALONE_ZOOKEEPER.name().equalsIgnoreCase(frameworkMode)) {
+ DAGProtos.ConfigurationProto confProtoBefore =
TezUtilsInternal.loadConfProtoFromText();
+ TezUtilsInternal.addUserSpecifiedTezConfiguration(
+ defaultConf, confProtoBefore.getConfKeyValuesList());
+
+ ZkAMRegistryClient registry = ZkAMRegistryClient.getClient(defaultConf);
+ registry.start();
+
+ // TODO: Expose retry counter and sleep time as config — in ZKconfig or
TezConfig?
+ while (!registry.isInitialized()) {
+ TimeUnit.SECONDS.sleep(5);
+ }
+
+ List<AMRecord> records = registry.getAllRecords();
+ if (records.isEmpty()) {
+ throw new RuntimeException("No AM found in ZooKeeper registry");
+ }
+ // TODO: Should we always get the first or there should be some
sophisticated logic?
+ AMRecord amRecord = records.getFirst();
+
+ host = amRecord.getHostName();
+ String portRange =
+ defaultConf.getTrimmed(TezConfiguration.TEZ_AM_TASK_AM_PORT_RANGE,
"12000-12000");
+ port = Integer.parseInt(portRange.split("[-,]")[0]);
+
+ appId = amRecord.getApplicationId().toString();
+ tokenIdentifier = appId;
+ attemptNumber = 1;
+
+ String baseContainerId = appId.replace("application_", "container_");
+ int randomSeq = (int) (Math.random() * 900000) + 100000;
+ containerIdentifier = baseContainerId + "_01_" + randomSeq;
+
+ String zkQuorum =
defaultConf.get(TezConfiguration.TEZ_AM_ZOOKEEPER_QUORUM);
+ ZkConfig zkconfig = new ZkConfig(defaultConf);
+ zkWorkerClient = CuratorFrameworkFactory.newClient(zkQuorum,
zkconfig.getRetryPolicy());
+ zkWorkerClient.start();
+
+ // Create Ephemeral node representing this worker
+ String workerPath = zkconfig.getZkTaskNameSpace() + "/" + appId + "/" +
containerIdentifier;
+ zkWorkerClient
+ .create()
+ .creatingParentsIfNeeded()
+ .withMode(CreateMode.EPHEMERAL)
+ .forPath(workerPath,
host.getBytes(java.nio.charset.StandardCharsets.UTF_8));
+
+ LOG.info("Registered TezChild Worker in ZK at path: {}", workerPath);
+
+ // FIX: Deterministic token
+ JobTokenIdentifier identifier = new JobTokenIdentifier(new Text(appId));
+ Token<JobTokenIdentifier> sessionToken =
+ new Token<>(identifier,
TezCommonUtils.createJobTokenSecretManager(defaultConf));
+ credentials.addToken(new Text("SessionToken"), sessionToken);
+
+ LOG.info("ZK Mode: Discovered AM {} at {}:{}", appId, host, port);
+
+ } else {
+ assert args.length == 5;
+ host = args[0];
+ port = Integer.parseInt(args[1]);
+ containerIdentifier = args[2];
+ tokenIdentifier = args[3];
+ attemptNumber = Integer.parseInt(args[4]);
Review Comment:
instead of if else, acquiring these could be refactored to separate methods
or even classes
also, if we feel that `TezChild` has changed so badly, I would also consider
introducing class hierarchy for that (not sure at the moment if composition or
inheritance), because another type of `TezChild` could also take care of
special things in the same JVM (e.g. shuffle handler)
##########
tez-runtime-library/src/main/java/org/apache/tez/runtime/library/common/shuffle/orderedgrouped/FetcherOrderedGrouped.java:
##########
@@ -180,7 +180,7 @@ public FetcherOrderedGrouped(HttpConnectionParams
httpConnectionParams,
@VisibleForTesting
protected void fetchNext() throws InterruptedException, IOException {
try {
- if (localDiskFetchEnabled && mapHost.getHost().equals(localShuffleHost)
&& mapHost.getPort() == localShufflePort) {
Review Comment:
we should clearly distinguish between local disk fetch and the containerized
approach in the first implementation
how local disk fetch optimization works on a classic yarn cluster is that
containers on the same host can copy data quickly: in docker containers we
cannot assume that the local folder used for shuffle intermediate data is
shared in any way, so to make this clear in the code, fetchers should be able
to know from the config framework mode, that we're in standalone zookeeper mode
and **should not** set up local fetch I believe
later, this same code path could still be optimized: e.g. fetchers to know
that even if they are in TezChild containers, they are on the same node + the
folder is shared, so they can leverage local fetch, but in the meantime, for
simplicity's sake, we can just disable it (TODO + clarifying code comment can
tell that this area needs further optimization)
however, a http fetch assumes a shuffle handler on the producer side, which
might be an additional burden on this POC, because another design decision has
to be made: how to run a ShuffleHandler, this is up to your fantasy
I think by a docker-compose you cannot co-locate tezchild-1 +
shufflehandler-1, tez-child2 + shufflehandler-2 (to make them share the same
hostname, you need to find a way to run a shuffle handler parallely for each
tezchild, sharing the same local folders, so shuffle handlers can serve them)
note that if shufflehandler somehow runs in the same container/jvm, they see
the same hostname, so you're sorted out with the local fetch optimization
this is obviously not the perfect production setup, but this ticket is the
ground POC of running tez DAGs in a distributed way without yarn
##########
tez-runtime-internals/src/main/java/org/apache/tez/runtime/task/TezChild.java:
##########
@@ -517,45 +531,112 @@ public static TezChild newTezChild(Configuration conf,
String host, int port, St
hadoopShim);
}
- public static void main(String[] args) throws IOException,
InterruptedException, TezException {
+ public static void main(String[] args) throws Exception {
TezClassLoader.setupTezClassLoader();
final Configuration defaultConf = new Configuration();
+ String frameworkMode = System.getenv(TezConstants.TEZ_FRAMEWORK_MODE);
+
+ String host, appId, tokenIdentifier, containerIdentifier;
+ int port, attemptNumber;
+ Credentials credentials = new Credentials();
+
+ if (STANDALONE_ZOOKEEPER.name().equalsIgnoreCase(frameworkMode)) {
+ DAGProtos.ConfigurationProto confProtoBefore =
TezUtilsInternal.loadConfProtoFromText();
+ TezUtilsInternal.addUserSpecifiedTezConfiguration(
+ defaultConf, confProtoBefore.getConfKeyValuesList());
+
+ ZkAMRegistryClient registry = ZkAMRegistryClient.getClient(defaultConf);
+ registry.start();
+
+ // TODO: Expose retry counter and sleep time as config — in ZKconfig or
TezConfig?
+ while (!registry.isInitialized()) {
+ TimeUnit.SECONDS.sleep(5);
+ }
+
+ List<AMRecord> records = registry.getAllRecords();
+ if (records.isEmpty()) {
+ throw new RuntimeException("No AM found in ZooKeeper registry");
+ }
+ // TODO: Should we always get the first or there should be some
sophisticated logic?
+ AMRecord amRecord = records.getFirst();
+
+ host = amRecord.getHostName();
+ String portRange =
+ defaultConf.getTrimmed(TezConfiguration.TEZ_AM_TASK_AM_PORT_RANGE,
"12000-12000");
+ port = Integer.parseInt(portRange.split("[-,]")[0]);
+
+ appId = amRecord.getApplicationId().toString();
+ tokenIdentifier = appId;
+ attemptNumber = 1;
+
+ String baseContainerId = appId.replace("application_", "container_");
+ int randomSeq = (int) (Math.random() * 900000) + 100000;
+ containerIdentifier = baseContainerId + "_01_" + randomSeq;
+
+ String zkQuorum =
defaultConf.get(TezConfiguration.TEZ_AM_ZOOKEEPER_QUORUM);
+ ZkConfig zkconfig = new ZkConfig(defaultConf);
+ zkWorkerClient = CuratorFrameworkFactory.newClient(zkQuorum,
zkconfig.getRetryPolicy());
+ zkWorkerClient.start();
+
+ // Create Ephemeral node representing this worker
+ String workerPath = zkconfig.getZkTaskNameSpace() + "/" + appId + "/" +
containerIdentifier;
+ zkWorkerClient
+ .create()
+ .creatingParentsIfNeeded()
+ .withMode(CreateMode.EPHEMERAL)
+ .forPath(workerPath,
host.getBytes(java.nio.charset.StandardCharsets.UTF_8));
+
+ LOG.info("Registered TezChild Worker in ZK at path: {}", workerPath);
+
+ // FIX: Deterministic token
+ JobTokenIdentifier identifier = new JobTokenIdentifier(new Text(appId));
+ Token<JobTokenIdentifier> sessionToken =
+ new Token<>(identifier,
TezCommonUtils.createJobTokenSecretManager(defaultConf));
+ credentials.addToken(new Text("SessionToken"), sessionToken);
+
+ LOG.info("ZK Mode: Discovered AM {} at {}:{}", appId, host, port);
+
+ } else {
+ assert args.length == 5;
+ host = args[0];
+ port = Integer.parseInt(args[1]);
+ containerIdentifier = args[2];
+ tokenIdentifier = args[3];
+ attemptNumber = Integer.parseInt(args[4]);
+
+ DAGProtos.ConfigurationProto confProto =
+
TezUtilsInternal.readUserSpecifiedTezConfiguration(System.getenv(Environment.PWD.name()));
+ TezUtilsInternal.addUserSpecifiedTezConfiguration(
+ defaultConf, confProto.getConfKeyValuesList());
+ }
Thread.setDefaultUncaughtExceptionHandler(new
YarnUncaughtExceptionHandler());
final String pid = System.getenv().get("JVM_PID");
+ String[] localDirs =
+
TezCommonUtils.getTrimmedStrings(System.getenv(Environment.LOCAL_DIRS.name()));
-
- assert args.length == 5;
- String host = args[0];
- int port = Integer.parseInt(args[1]);
- final String containerIdentifier = args[2];
- final String tokenIdentifier = args[3];
- final int attemptNumber = Integer.parseInt(args[4]);
- final String[] localDirs =
TezCommonUtils.getTrimmedStrings(System.getenv(Environment.LOCAL_DIRS
- .name()));
- CallerContext.setCurrent(new
CallerContext.Builder("tez_"+tokenIdentifier).build());
- LOG.info("TezChild starting with PID=" + pid + ", containerIdentifier=" +
containerIdentifier);
+ CallerContext.setCurrent(new CallerContext.Builder("tez_" +
tokenIdentifier).build());
+ LOG.info("TezChild starting with PID={}, containerIdentifier={}", pid,
containerIdentifier);
Review Comment:
in docker containers, pid is going to be 1 always, so depending on the
framework mode, `JVM_PID` is not always valid to be choosen
##########
tez-dist/src/docker/docker-compose.yml:
##########
@@ -126,6 +130,36 @@ services:
datanode:
condition: service_started
+ tez-child-1:
+ image: apache/tez:${TEZ_VERSION:-1.0.0-SNAPSHOT}
+ container_name: tez-child-1
+ hostname: tez-child-1
+ networks:
+ - hadoop-network
+ volumes:
+ - tez_shared_data:/data
+ - tez_shared_tmp:/tmp
Review Comment:
as implied in another comment, let's assume first that tez task containers
do have a local (not shared) folder for intermediate data, so they can be later
scheduled to any node in the world and keep on working (we decide local fetch
optimization later)
##########
tez-dist/src/docker/docker-compose.yml:
##########
@@ -126,6 +130,36 @@ services:
datanode:
condition: service_started
+ tez-child-1:
+ image: apache/tez:${TEZ_VERSION:-1.0.0-SNAPSHOT}
+ container_name: tez-child-1
+ hostname: tez-child-1
+ networks:
+ - hadoop-network
Review Comment:
nit: let's try not to use "hadoop" in the network name, as especially with
this patch, we're moving away from the classic hadoop setups
##########
tez-dist/src/docker/docker-compose.yml:
##########
@@ -126,6 +130,36 @@ services:
datanode:
condition: service_started
+ tez-child-1:
Review Comment:
instead of defining separate tez child containers, try to simply scale them,
like `llapdaemon` in hive, see:
https://github.com/apache/hive/blob/9e38b8a3c58720899f413fe2531fed4138fb0a7f/packaging/src/docker/docker-compose.yml#L165
and the starter script:
https://github.com/apache/hive/blob/9e38b8a3c58720899f413fe2531fed4138fb0a7f/packaging/src/docker/start-hive.sh#L32
you can also add a `start-tez.sh` script here and refer to it in README: a
dev/user should be able to start a tez cluster on top of docker-compose without
any prior knowledge, just by this script
##########
tez-dist/src/docker/README.md:
##########
@@ -0,0 +1,196 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+# Apache Tez Docker
+
+This directory contains a unified Docker implementation for running TezAM
+and TezChild process from a single container image. Based on
+`TEZ_COMPONENT` environment variable the entrypoint is dynamically selected
+
+1. Building the docker image:
+
+ ```bash
+ mvn clean install -DskipTests -Pdocker
+ ```
+
+ Alternatively, you can build it explicitly via the provided script:
+
+ ```bash
+ ./tez-dist/src/docker/build.sh -tez <version> -repo apache
+ ```
+
+2. Local Zookeeper Setup (Standalone):
Review Comment:
I think if we have a docker-compose file, these separate docker run commands
are not supposed to be documented at all, it's verbose, and we're not
encouraging users to do so, instead, use a starter script that utilizes the
docker-compose file
##########
tez-dist/src/docker/README.md:
##########
@@ -0,0 +1,196 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+# Apache Tez Docker
+
+This directory contains a unified Docker implementation for running TezAM
+and TezChild process from a single container image. Based on
+`TEZ_COMPONENT` environment variable the entrypoint is dynamically selected
+
+1. Building the docker image:
+
+ ```bash
+ mvn clean install -DskipTests -Pdocker
+ ```
+
+ Alternatively, you can build it explicitly via the provided script:
+
+ ```bash
+ ./tez-dist/src/docker/build.sh -tez <version> -repo apache
+ ```
+
+2. Local Zookeeper Setup (Standalone):
+
+ If you are running the AM container use the official Docker
+ image (Refer to docker-compose.yml):
+
+ ```bash
+ docker pull zookeeper:3.8.4
+
+ docker run -d \
+ --name zookeeper-server \
+ -p 2181:2181 \
+ -p 8080:8080 \
+ -e ZOO_MY_ID=1 \
+ zookeeper:3.8.4
+ ```
+
+3. Running the Tez containers explicitly:
+
+ **Running the Tez AM:**
+
+ ```bash
+ export TEZ_VERSION=1.0.0-SNAPSHOT
+
+ docker run --rm \
+ -p 10001:10001 \
+ --env-file tez-dist/src/docker/am.env \
+ --name tez-am \
+ --hostname localhost \
+ apache/tez:$TEZ_VERSION
+ ```
+
+ * `TEZ_VERSION` corresponds to the Maven `${project.version}`.
+ Set this environment variable in your shell before running the commands.
+
+ * Expose ports using the `-p` flag based on the
+ `tez.am.client.am.port-range` property in `tez-site.xml`.
+
+ * The `--hostname` flag configures the container's hostname, allowing
+ services on the host (e.g., macOS) to connect to it.
+
+ * Ensure the `--env-file` flag is included, or at a minimum, pass
+ `-e TEZ_FRAMEWORK_MODE=STANDALONE_ZOOKEEPER` and `-e TEZ_COMPONENT=AM`
+ to the `docker run` command.
+
+ **Running the Tez Child:**
+
+ The child container requires specific arguments (`<am-host> <am-port>
+ <container-id> <token-id> <attempt-number>`) to connect back to the
+ Application Master.
+
+ Assuming your AM is running on `localhost` port `10001`, and the AM
+ assigned the container ID `container_1703023223000_0001_01_000001`:
+
+ ```bash
+ docker run --rm \
+ --network host \
+ --env-file tez-dist/src/docker/child.env \
+ --name tez-child \
+ --hostname localhost \
+ apache/tez:1.0.0-SNAPSHOT \
+ localhost 10001 container_1703023223000_0001_01_000001 dummy_token_abc 1
Review Comment:
it's strange that the docker run command for an AM doesn't contain the
artificial application id, but same for task container does, I wish this could
become shorter...not sure yet how to proceed, maybe after the docker-compose
file and a corresponding starter script is going to take care of this
##########
tez-dist/src/docker/README.md:
##########
@@ -0,0 +1,196 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+# Apache Tez Docker
+
+This directory contains a unified Docker implementation for running TezAM
+and TezChild process from a single container image. Based on
+`TEZ_COMPONENT` environment variable the entrypoint is dynamically selected
+
+1. Building the docker image:
+
+ ```bash
+ mvn clean install -DskipTests -Pdocker
+ ```
+
+ Alternatively, you can build it explicitly via the provided script:
+
+ ```bash
+ ./tez-dist/src/docker/build.sh -tez <version> -repo apache
+ ```
+
+2. Local Zookeeper Setup (Standalone):
+
+ If you are running the AM container use the official Docker
+ image (Refer to docker-compose.yml):
+
+ ```bash
+ docker pull zookeeper:3.8.4
+
+ docker run -d \
+ --name zookeeper-server \
+ -p 2181:2181 \
+ -p 8080:8080 \
+ -e ZOO_MY_ID=1 \
+ zookeeper:3.8.4
+ ```
+
+3. Running the Tez containers explicitly:
+
+ **Running the Tez AM:**
+
+ ```bash
+ export TEZ_VERSION=1.0.0-SNAPSHOT
+
+ docker run --rm \
+ -p 10001:10001 \
+ --env-file tez-dist/src/docker/am.env \
+ --name tez-am \
+ --hostname localhost \
+ apache/tez:$TEZ_VERSION
+ ```
+
+ * `TEZ_VERSION` corresponds to the Maven `${project.version}`.
+ Set this environment variable in your shell before running the commands.
+
+ * Expose ports using the `-p` flag based on the
+ `tez.am.client.am.port-range` property in `tez-site.xml`.
+
+ * The `--hostname` flag configures the container's hostname, allowing
+ services on the host (e.g., macOS) to connect to it.
+
+ * Ensure the `--env-file` flag is included, or at a minimum, pass
+ `-e TEZ_FRAMEWORK_MODE=STANDALONE_ZOOKEEPER` and `-e TEZ_COMPONENT=AM`
+ to the `docker run` command.
+
+ **Running the Tez Child:**
+
+ The child container requires specific arguments (`<am-host> <am-port>
+ <container-id> <token-id> <attempt-number>`) to connect back to the
+ Application Master.
+
+ Assuming your AM is running on `localhost` port `10001`, and the AM
+ assigned the container ID `container_1703023223000_0001_01_000001`:
+
+ ```bash
+ docker run --rm \
+ --network host \
+ --env-file tez-dist/src/docker/child.env \
+ --name tez-child \
+ --hostname localhost \
+ apache/tez:1.0.0-SNAPSHOT \
+ localhost 10001 container_1703023223000_0001_01_000001 dummy_token_abc 1
+ ```
+
+4. Debugging the Tez containers:
+ Uncomment the `JAVA_TOOL_OPTIONS` in `am.env` (or `child.env` for
+ port 5006) and expose the debug port using `-p` flag:
+
+ ```bash
+ docker run --rm \
+ -p 10001:10001 -p 5005:5005 \
+ --env-file tez-dist/src/docker/am.env \
+ --name tez-am \
+ --hostname localhost \
+ apache/tez:$TEZ_VERSION
+ ```
+
+5. To override the tez-site.xml in docker image use:
+
+ * Set the `TEZ_CUSTOM_CONF_DIR` environment variable in `am.env` /
+ `child.env` or via the `docker run` command (e.g.,
+ `/opt/tez/custom-conf`).
+
+ ```bash
+ export TEZ_SITE_PATH=$(pwd)/tez-dist/src/docker/conf/tez-site.xml
+
+ docker run --rm \
+ -p 10001:10001 \
+ --env-file tez-dist/src/docker/am.env \
+ -v "$TEZ_SITE_PATH:/opt/tez/custom-conf/tez-site.xml" \
+ --name tez-am \
+ --hostname localhost \
+ apache/tez:$TEZ_VERSION
+ ```
+
+6. To add plugin jars in docker image use:
+
+ * The plugin directory path inside the Docker container is fixed at
+ `/opt/tez/plugins`.
+
+ ```bash
+ docker run --rm \
+ -p 10001:10001 \
+ --env-file tez-dist/src/docker/am.env \
+ -v "/path/to/your/local/plugins:/opt/tez/plugins" \
+ --name tez-am \
+ --hostname localhost \
+ apache/tez:$TEZ_VERSION
+ ```
Review Comment:
this section can be replaced with some tips pointing to jars:
```
export TEZ_PLUGIN_JARS=/path/to/your/local/plugins
./start-tez.sh
```
this will make the testing with custom jars extremely easy
##########
tez-dist/src/docker/README.md:
##########
@@ -0,0 +1,196 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+# Apache Tez Docker
+
+This directory contains a unified Docker implementation for running TezAM
+and TezChild process from a single container image. Based on
+`TEZ_COMPONENT` environment variable the entrypoint is dynamically selected
+
+1. Building the docker image:
+
+ ```bash
+ mvn clean install -DskipTests -Pdocker
+ ```
+
+ Alternatively, you can build it explicitly via the provided script:
+
+ ```bash
+ ./tez-dist/src/docker/build.sh -tez <version> -repo apache
+ ```
+
+2. Local Zookeeper Setup (Standalone):
+
+ If you are running the AM container use the official Docker
+ image (Refer to docker-compose.yml):
+
+ ```bash
+ docker pull zookeeper:3.8.4
+
+ docker run -d \
+ --name zookeeper-server \
+ -p 2181:2181 \
+ -p 8080:8080 \
+ -e ZOO_MY_ID=1 \
+ zookeeper:3.8.4
+ ```
+
+3. Running the Tez containers explicitly:
+
+ **Running the Tez AM:**
+
+ ```bash
+ export TEZ_VERSION=1.0.0-SNAPSHOT
+
+ docker run --rm \
+ -p 10001:10001 \
+ --env-file tez-dist/src/docker/am.env \
+ --name tez-am \
+ --hostname localhost \
+ apache/tez:$TEZ_VERSION
+ ```
+
+ * `TEZ_VERSION` corresponds to the Maven `${project.version}`.
+ Set this environment variable in your shell before running the commands.
+
+ * Expose ports using the `-p` flag based on the
+ `tez.am.client.am.port-range` property in `tez-site.xml`.
+
+ * The `--hostname` flag configures the container's hostname, allowing
+ services on the host (e.g., macOS) to connect to it.
+
+ * Ensure the `--env-file` flag is included, or at a minimum, pass
+ `-e TEZ_FRAMEWORK_MODE=STANDALONE_ZOOKEEPER` and `-e TEZ_COMPONENT=AM`
+ to the `docker run` command.
+
+ **Running the Tez Child:**
+
+ The child container requires specific arguments (`<am-host> <am-port>
+ <container-id> <token-id> <attempt-number>`) to connect back to the
+ Application Master.
+
+ Assuming your AM is running on `localhost` port `10001`, and the AM
+ assigned the container ID `container_1703023223000_0001_01_000001`:
+
+ ```bash
+ docker run --rm \
+ --network host \
+ --env-file tez-dist/src/docker/child.env \
+ --name tez-child \
+ --hostname localhost \
+ apache/tez:1.0.0-SNAPSHOT \
+ localhost 10001 container_1703023223000_0001_01_000001 dummy_token_abc 1
+ ```
+
+4. Debugging the Tez containers:
+ Uncomment the `JAVA_TOOL_OPTIONS` in `am.env` (or `child.env` for
+ port 5006) and expose the debug port using `-p` flag:
+
+ ```bash
+ docker run --rm \
+ -p 10001:10001 -p 5005:5005 \
+ --env-file tez-dist/src/docker/am.env \
+ --name tez-am \
+ --hostname localhost \
+ apache/tez:$TEZ_VERSION
+ ```
+
+5. To override the tez-site.xml in docker image use:
+
+ * Set the `TEZ_CUSTOM_CONF_DIR` environment variable in `am.env` /
+ `child.env` or via the `docker run` command (e.g.,
+ `/opt/tez/custom-conf`).
+
+ ```bash
+ export TEZ_SITE_PATH=$(pwd)/tez-dist/src/docker/conf/tez-site.xml
+
+ docker run --rm \
+ -p 10001:10001 \
+ --env-file tez-dist/src/docker/am.env \
+ -v "$TEZ_SITE_PATH:/opt/tez/custom-conf/tez-site.xml" \
+ --name tez-am \
+ --hostname localhost \
+ apache/tez:$TEZ_VERSION
+ ```
+
+6. To add plugin jars in docker image use:
+
+ * The plugin directory path inside the Docker container is fixed at
+ `/opt/tez/plugins`.
+
+ ```bash
+ docker run --rm \
+ -p 10001:10001 \
+ --env-file tez-dist/src/docker/am.env \
+ -v "/path/to/your/local/plugins:/opt/tez/plugins" \
+ --name tez-am \
+ --hostname localhost \
+ apache/tez:$TEZ_VERSION
+ ```
+
+7. Using Docker Compose (Local Testing Cluster):
+
+ The provided `docker-compose.yml` offers a complete, minimal Hadoop
+ ecosystem to test Tez in a distributed manner locally without setting
+ up a real cluster.
+
+ **Services Included:**
+
+ * **namenode & datanode:** A minimal Apache Hadoop HDFS cluster
+ (lean image)
+
+ * **zookeeper:** Required by the Tez AM for standalone session
+ discovery
+
+ * **tez-am:** It automatically waits for Zookeeper and HDFS to
+ be healthy before starting up.
+
+ * **tez-child:** TBD
+
+ **To start the full cluster:**
+
+ ```bash
+ docker-compose -f tez-dist/src/docker/docker-compose.yml up -d
+ ```
+
+ **To monitor the Application Master logs:**
+
+ ```bash
+ docker-compose -f tez-dist/src/docker/docker-compose.yml logs -f tez-am
+ ```
+
+ **To shut down the cluster and clean up volumes (HDFS/Zookeeper data):**
+
+ ```bash
+ docker-compose -f tez-dist/src/docker/docker-compose.yml down -v
+ ```
+
+8. To mount custom plugins or JARs required by Tez AM (e.g., for split
+ generation — typically the hive-exec jar, but in general, any UDFs or
+ dependencies previously managed via YARN localization:
+
+ * Create a directory `tez-plugins` and add all required jars.
+
+ * Uncomment the following lines in docker compose under the `tez-am`
+ and `tez-child` services to mount this directory as a volume to
+ `/opt/tez/plugins` in the docker container.
+
+ ```yaml
+ volumes:
+ - ./tez-plugins:/opt/tez/plugins
+ ```
Review Comment:
this should be taken care of by the same as above in 6)
##########
tez-runtime-internals/src/main/java/org/apache/tez/runtime/task/TezChild.java:
##########
@@ -517,45 +531,112 @@ public static TezChild newTezChild(Configuration conf,
String host, int port, St
hadoopShim);
}
- public static void main(String[] args) throws IOException,
InterruptedException, TezException {
+ public static void main(String[] args) throws Exception {
TezClassLoader.setupTezClassLoader();
final Configuration defaultConf = new Configuration();
+ String frameworkMode = System.getenv(TezConstants.TEZ_FRAMEWORK_MODE);
+
+ String host, appId, tokenIdentifier, containerIdentifier;
+ int port, attemptNumber;
+ Credentials credentials = new Credentials();
+
+ if (STANDALONE_ZOOKEEPER.name().equalsIgnoreCase(frameworkMode)) {
+ DAGProtos.ConfigurationProto confProtoBefore =
TezUtilsInternal.loadConfProtoFromText();
+ TezUtilsInternal.addUserSpecifiedTezConfiguration(
+ defaultConf, confProtoBefore.getConfKeyValuesList());
+
+ ZkAMRegistryClient registry = ZkAMRegistryClient.getClient(defaultConf);
+ registry.start();
+
+ // TODO: Expose retry counter and sleep time as config — in ZKconfig or
TezConfig?
+ while (!registry.isInitialized()) {
+ TimeUnit.SECONDS.sleep(5);
+ }
+
+ List<AMRecord> records = registry.getAllRecords();
+ if (records.isEmpty()) {
+ throw new RuntimeException("No AM found in ZooKeeper registry");
+ }
+ // TODO: Should we always get the first or there should be some
sophisticated logic?
+ AMRecord amRecord = records.getFirst();
+
+ host = amRecord.getHostName();
+ String portRange =
+ defaultConf.getTrimmed(TezConfiguration.TEZ_AM_TASK_AM_PORT_RANGE,
"12000-12000");
+ port = Integer.parseInt(portRange.split("[-,]")[0]);
+
+ appId = amRecord.getApplicationId().toString();
+ tokenIdentifier = appId;
+ attemptNumber = 1;
+
+ String baseContainerId = appId.replace("application_", "container_");
+ int randomSeq = (int) (Math.random() * 900000) + 100000;
+ containerIdentifier = baseContainerId + "_01_" + randomSeq;
+
+ String zkQuorum =
defaultConf.get(TezConfiguration.TEZ_AM_ZOOKEEPER_QUORUM);
+ ZkConfig zkconfig = new ZkConfig(defaultConf);
+ zkWorkerClient = CuratorFrameworkFactory.newClient(zkQuorum,
zkconfig.getRetryPolicy());
+ zkWorkerClient.start();
+
+ // Create Ephemeral node representing this worker
+ String workerPath = zkconfig.getZkTaskNameSpace() + "/" + appId + "/" +
containerIdentifier;
+ zkWorkerClient
+ .create()
+ .creatingParentsIfNeeded()
+ .withMode(CreateMode.EPHEMERAL)
+ .forPath(workerPath,
host.getBytes(java.nio.charset.StandardCharsets.UTF_8));
Review Comment:
instead of a random + create(), an incremental + retry logic should be
implemented here:
1. try to acquire `n`, pass
2. if fails with `n`, try `n+1`
##########
tez-runtime-library/src/main/java/org/apache/tez/runtime/library/common/shuffle/ShuffleUtils.java:
##########
@@ -316,6 +316,9 @@ static ByteBuffer generateDMEPayload(boolean
sendEmptyPartitionDetails,
if (!sendEmptyPartitionDetails || outputGenerated) {
String host = context.getExecutionContext().getHostName();
+ if (host == null) {
Review Comment:
I believe we should not simply hardcode "localhost" here: if this caused an
NPE, it means ExecutionContext needs to be improved and prepared for the
unmanaged sessions scenario
let's assume that we're going to run `TezChild` containers as part of a
docker-compose and later as k8s pods in a deployment or statefulset: so how we
create an ExecutionContext now should be in line with that kind
e.g. currently we get NM_HOST:
https://github.com/apache/tez/blob/17d15490cedab7d18a4d4c1f83374e30c58a363f/tez-runtime-internals/src/main/java/org/apache/tez/runtime/task/TezChild.java#L563
this is Yarn-specific, but fortunately you worked on TEZ-4689, so whatever
you did there for node context, it should be followed here for execution
context as well
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]