Skip to content

Commit 50a1e20

Browse files
committed
MAPREDUCE-3940. ContainerTokens should have an expiry interval. Contributed by Siddharth Seth and Vinod Kumar Vavilapalli.
git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1359910 13f79535-47bb-0310-9956-ffa450edef68
1 parent 0a22e79 commit 50a1e20

File tree

18 files changed

+217
-56
lines changed

18 files changed

+217
-56
lines changed

hadoop-mapreduce-project/CHANGES.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,9 @@ Release 0.23.3 - UNRELEASED
670670
MAPREDUCE-4252. MR2 job never completes with 1 pending task (Tom White via
671671
bobby)
672672

673+
MAPREDUCE-3940. ContainerTokens should have an expiry interval. (Siddharth
674+
Seth and Vinod Kumar Vavilapalli via vinodkv)
675+
673676
Release 0.23.2 - UNRELEASED
674677

675678
INCOMPATIBLE CHANGES

hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/test/java/org/apache/hadoop/mapreduce/v2/app/TestRMContainerAllocator.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import static org.mockito.Mockito.verify;
3030
import static org.mockito.Mockito.when;
3131

32+
import java.io.IOException;
3233
import java.util.ArrayList;
3334
import java.util.Arrays;
3435
import java.util.HashMap;
@@ -86,11 +87,13 @@
8687
import org.apache.hadoop.yarn.factory.providers.RecordFactoryProvider;
8788
import org.apache.hadoop.yarn.server.resourcemanager.MockNM;
8889
import org.apache.hadoop.yarn.server.resourcemanager.MockRM;
90+
import org.apache.hadoop.yarn.server.resourcemanager.RMContext;
8991
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp;
9092
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.Allocation;
9193
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.ResourceScheduler;
9294
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.event.SchedulerEvent;
9395
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.fifo.FifoScheduler;
96+
import org.apache.hadoop.yarn.server.security.ContainerTokenSecretManager;
9497
import org.apache.hadoop.yarn.util.BuilderUtils;
9598
import org.junit.After;
9699
import org.junit.Test;
@@ -352,7 +355,7 @@ public void handle(SchedulerEvent event) {
352355
}
353356
@Override
354357
protected ResourceScheduler createScheduler() {
355-
return new MyFifoScheduler();
358+
return new MyFifoScheduler(this.getRMContext());
356359
}
357360
}
358361

@@ -1091,6 +1094,19 @@ public void testBlackListedNodesWithSchedulingToThatNode() throws Exception {
10911094
}
10921095

10931096
private static class MyFifoScheduler extends FifoScheduler {
1097+
1098+
public MyFifoScheduler(RMContext rmContext) {
1099+
super();
1100+
try {
1101+
Configuration conf = new Configuration();
1102+
reinitialize(conf, new ContainerTokenSecretManager(conf),
1103+
rmContext);
1104+
} catch (IOException ie) {
1105+
LOG.info("add application failed with ", ie);
1106+
assert (false);
1107+
}
1108+
}
1109+
10941110
// override this to copy the objects otherwise FifoScheduler updates the
10951111
// numContainers in same objects as kept by RMContainerAllocator
10961112
@Override

hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/api/records/ContainerToken.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,46 +50,46 @@ public interface ContainerToken extends DelegationToken {
5050
*/
5151
@Public
5252
@Stable
53-
public abstract ByteBuffer getIdentifier();
53+
ByteBuffer getIdentifier();
5454

5555
@Private
5656
@Stable
57-
public abstract void setIdentifier(ByteBuffer identifier);
57+
void setIdentifier(ByteBuffer identifier);
5858

5959
/**
6060
* Get the token password
6161
* @return token password
6262
*/
6363
@Public
6464
@Stable
65-
public abstract ByteBuffer getPassword();
65+
ByteBuffer getPassword();
6666

6767
@Private
6868
@Stable
69-
public abstract void setPassword(ByteBuffer password);
69+
void setPassword(ByteBuffer password);
7070

7171
/**
7272
* Get the token kind.
7373
* @return token kind
7474
*/
7575
@Public
7676
@Stable
77-
public abstract String getKind();
77+
String getKind();
7878

7979
@Private
8080
@Stable
81-
public abstract void setKind(String kind);
81+
void setKind(String kind);
8282

8383
/**
8484
* Get the service to which the token is allocated.
8585
* @return service to which the token is allocated
8686
*/
8787
@Public
8888
@Stable
89-
public abstract String getService();
89+
String getService();
9090

9191
@Private
9292
@Stable
93-
public abstract void setService(String service);
93+
void setService(String service);
9494

9595
}

hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/api/impl/pb/client/ContainerManagerPBClientImpl.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import java.io.IOException;
2222
import java.net.InetSocketAddress;
23+
import java.io.Closeable;
2324

2425
import org.apache.hadoop.conf.Configuration;
2526
import org.apache.hadoop.ipc.ProtobufRpcEngine;
@@ -49,7 +50,8 @@
4950

5051
import com.google.protobuf.ServiceException;
5152

52-
public class ContainerManagerPBClientImpl implements ContainerManager {
53+
public class ContainerManagerPBClientImpl implements ContainerManager,
54+
Closeable {
5355

5456
// Not a documented config. Only used for tests
5557
static final String NM_COMMAND_TIMEOUT = YarnConfiguration.YARN_PREFIX

hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/security/ContainerTokenIdentifier.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@
3535
import org.apache.hadoop.yarn.api.records.Resource;
3636
import org.apache.hadoop.yarn.util.BuilderUtils;
3737

38+
/**
39+
* TokenIdentifier for a container. Encodes {@link ContainerId},
40+
* {@link Resource} needed by the container and the target NMs host-address.
41+
*
42+
*/
3843
public class ContainerTokenIdentifier extends TokenIdentifier {
3944

4045
private static Log LOG = LogFactory.getLog(ContainerTokenIdentifier.class);
@@ -44,14 +49,19 @@ public class ContainerTokenIdentifier extends TokenIdentifier {
4449
private ContainerId containerId;
4550
private String nmHostAddr;
4651
private Resource resource;
52+
private long expiryTimeStamp;
4753

4854
public ContainerTokenIdentifier(ContainerId containerID, String hostName,
49-
Resource r) {
55+
Resource r, long expiryTimeStamp) {
5056
this.containerId = containerID;
5157
this.nmHostAddr = hostName;
5258
this.resource = r;
59+
this.expiryTimeStamp = expiryTimeStamp;
5360
}
5461

62+
/**
63+
* Default constructor needed by RPC layer/SecretManager.
64+
*/
5565
public ContainerTokenIdentifier() {
5666
}
5767

@@ -67,6 +77,10 @@ public Resource getResource() {
6777
return this.resource;
6878
}
6979

80+
public long getExpiryTimeStamp() {
81+
return this.expiryTimeStamp;
82+
}
83+
7084
@Override
7185
public void write(DataOutput out) throws IOException {
7286
LOG.debug("Writing ContainerTokenIdentifier to RPC layer: " + this);
@@ -79,6 +93,7 @@ public void write(DataOutput out) throws IOException {
7993
out.writeInt(this.containerId.getId());
8094
out.writeUTF(this.nmHostAddr);
8195
out.writeInt(this.resource.getMemory());
96+
out.writeLong(this.expiryTimeStamp);
8297
}
8398

8499
@Override
@@ -91,6 +106,7 @@ public void readFields(DataInput in) throws IOException {
91106
.readInt());
92107
this.nmHostAddr = in.readUTF();
93108
this.resource = BuilderUtils.newResource(in.readInt());
109+
this.expiryTimeStamp = in.readLong();
94110
}
95111

96112
@Override
@@ -103,6 +119,7 @@ public UserGroupInformation getUser() {
103119
return UserGroupInformation.createRemoteUser(this.containerId.toString());
104120
}
105121

122+
// TODO: Needed?
106123
@InterfaceAudience.Private
107124
public static class Renewer extends Token.TrivialRenewer {
108125
@Override

hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/security/ContainerTokenSecretManager.java

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,29 @@
1818

1919
package org.apache.hadoop.yarn.server.security;
2020

21+
import java.nio.ByteBuffer;
2122
import java.util.Map;
2223
import java.util.concurrent.ConcurrentHashMap;
2324

2425
import javax.crypto.SecretKey;
2526

2627
import org.apache.commons.logging.Log;
2728
import org.apache.commons.logging.LogFactory;
29+
import org.apache.hadoop.conf.Configuration;
2830
import org.apache.hadoop.security.token.SecretManager;
31+
import org.apache.hadoop.yarn.api.records.ContainerId;
32+
import org.apache.hadoop.yarn.api.records.ContainerToken;
33+
import org.apache.hadoop.yarn.api.records.NodeId;
34+
import org.apache.hadoop.yarn.api.records.Resource;
35+
import org.apache.hadoop.yarn.conf.YarnConfiguration;
2936
import org.apache.hadoop.yarn.security.ContainerTokenIdentifier;
37+
import org.apache.hadoop.yarn.util.BuilderUtils;
3038

39+
/**
40+
* SecretManager for ContainerTokens. Used by both RM and NM and hence is
41+
* present in yarn-server-common package.
42+
*
43+
*/
3144
public class ContainerTokenSecretManager extends
3245
SecretManager<ContainerTokenIdentifier> {
3346

@@ -36,7 +49,34 @@ public class ContainerTokenSecretManager extends
3649

3750
Map<String, SecretKey> secretkeys =
3851
new ConcurrentHashMap<String, SecretKey>();
39-
52+
53+
private final long containerTokenExpiryInterval;
54+
55+
public ContainerTokenSecretManager(Configuration conf) {
56+
this.containerTokenExpiryInterval =
57+
conf.getInt(YarnConfiguration.RM_CONTAINER_ALLOC_EXPIRY_INTERVAL_MS,
58+
YarnConfiguration.DEFAULT_RM_CONTAINER_ALLOC_EXPIRY_INTERVAL_MS);
59+
}
60+
61+
public ContainerToken createContainerToken(ContainerId containerId,
62+
NodeId nodeId, Resource capability) {
63+
try {
64+
long expiryTimeStamp =
65+
System.currentTimeMillis() + containerTokenExpiryInterval;
66+
ContainerTokenIdentifier tokenIdentifier =
67+
new ContainerTokenIdentifier(containerId, nodeId.toString(),
68+
capability, expiryTimeStamp);
69+
return BuilderUtils.newContainerToken(nodeId,
70+
ByteBuffer.wrap(this.createPassword(tokenIdentifier)), tokenIdentifier);
71+
} catch (IllegalArgumentException e) {
72+
// this could be because DNS is down - in which case we just want
73+
// to retry and not bring RM down. Caller should note and act on the fact
74+
// that container is not creatable.
75+
LOG.error("Error trying to create new container", e);
76+
return null;
77+
}
78+
}
79+
4080
// Used by master for generation of secretyKey per host
4181
public SecretKey createAndGetSecretKey(CharSequence hostName) {
4282
String hostNameStr = hostName.toString();

hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/NodeManager.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ public void init(Configuration conf) {
116116
if (UserGroupInformation.isSecurityEnabled()) {
117117
LOG.info("Security is enabled on NodeManager. "
118118
+ "Creating ContainerTokenSecretManager");
119-
this.containerTokenSecretManager = new ContainerTokenSecretManager();
119+
this.containerTokenSecretManager = new ContainerTokenSecretManager(conf);
120120
}
121121

122122
this.aclsManager = new ApplicationACLsManager(conf);

hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/ContainerManagerImpl.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,15 @@ private void authorizeRequest(ContainerId containerID,
324324
+ containerIDStr);
325325
} else {
326326

327+
// Ensure the token is not expired.
328+
// Token expiry is not checked for stopContainer/getContainerStatus
329+
if (tokenId.getExpiryTimeStamp() < System.currentTimeMillis()) {
330+
unauthorized = true;
331+
messageBuilder.append("\nThis token is expired. current time is "
332+
+ System.currentTimeMillis() + " found "
333+
+ tokenId.getExpiryTimeStamp());
334+
}
335+
327336
Resource resource = tokenId.getResource();
328337
if (!resource.equals(launchContext.getResource())) {
329338
unauthorized = true;

hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestEventFlow.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,8 @@ public void testSuccessfulContainerLaunch() throws InterruptedException,
8686
healthChecker.init(conf);
8787
LocalDirsHandlerService dirsHandler = healthChecker.getDiskHandler();
8888
NodeManagerMetrics metrics = NodeManagerMetrics.create();
89-
ContainerTokenSecretManager containerTokenSecretManager = new ContainerTokenSecretManager();
89+
ContainerTokenSecretManager containerTokenSecretManager =
90+
new ContainerTokenSecretManager(conf);
9091
NodeStatusUpdater nodeStatusUpdater =
9192
new NodeStatusUpdaterImpl(context, dispatcher, healthChecker, metrics, containerTokenSecretManager) {
9293
@Override

hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/BaseContainerManagerTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ public abstract class BaseContainerManagerTest {
7070
protected static File localLogDir;
7171
protected static File remoteLogDir;
7272
protected static File tmpDir;
73-
protected ContainerTokenSecretManager containerTokenSecretManager = new ContainerTokenSecretManager();
73+
protected ContainerTokenSecretManager containerTokenSecretManager =
74+
new ContainerTokenSecretManager(new Configuration());
7475

7576
protected final NodeManagerMetrics metrics = NodeManagerMetrics.create();
7677

0 commit comments

Comments
 (0)